import streamlit as st
from matplotlib.textpath import TextPath
from matplotlib.font_manager import FontProperties
from matplotlib.path import Path as MplPath

# ─── Text → SVG path helper ───────────────────────────────────────────────────
def tp(text, cx, cy, font_size, anchor='middle', fill='#444444'):
    """Convert a string to an SVG <path> element (no <text> tags)."""
    if not text:
        return ''
    fp = FontProperties(family='DejaVu Sans')
    mtp = TextPath((0, 0), text, size=font_size, prop=fp)
    bb  = mtp.get_extents()
    tw  = bb.x1 - bb.x0

    if anchor == 'middle':
        ox = cx - tw / 2 - bb.x0
    elif anchor == 'end':
        ox = cx - tw - bb.x0
    else:
        ox = cx - bb.x0

    # Vertical: centre of glyph bounding box → cy
    text_mid_y = (bb.y0 + bb.y1) / 2
    oy = cy + text_mid_y          # SVG y = oy − matplotlib y

    verts = mtp.vertices
    codes = mtp.codes
    d = []
    i = 0
    n = len(codes)
    while i < n:
        code = codes[i]
        vx, vy = verts[i]
        sx = vx + ox;  sy = oy - vy
        if code == MplPath.MOVETO:
            d.append(f'M {sx:.2f},{sy:.2f}')
            i += 1
        elif code == MplPath.LINETO:
            d.append(f'L {sx:.2f},{sy:.2f}')
            i += 1
        elif code == MplPath.CURVE3:
            vx2, vy2 = verts[i+1]
            d.append(f'Q {sx:.2f},{sy:.2f} {vx2+ox:.2f},{oy-vy2:.2f}')
            i += 2
        elif code == MplPath.CURVE4:
            vx2, vy2 = verts[i+1];  vx3, vy3 = verts[i+2]
            d.append(f'C {sx:.2f},{sy:.2f} {vx2+ox:.2f},{oy-vy2:.2f} {vx3+ox:.2f},{oy-vy3:.2f}')
            i += 3
        elif code == MplPath.CLOSEPOLY:
            d.append('Z')
            i += 1
        else:
            i += 1
    return f'<path d="{" ".join(d)}" fill="{fill}" stroke="none"/>'


# ─── Language packages ────────────────────────────────────────────────────────
LANG = {
    "SL": {
        "app_title":     "🔌 Generator sheme con ARBURG",
        "app_sub":       "Konfigurirajte grelne cone in izvozite SVG.",
        "general":       "⚙️ Splošne nastavitve",
        "diag_title":    "Naziv diagrama",
        "num_zones":     "Število con",
        "zone_width":    "Širina cone (px)",
        "svg_height":    "Višina diagrama (px)",
        "symbol":        "📐 Nastavitve simbolov",
        "show_pol":      "Prikaži oznake +/−",
        "show_zlbl":     "Prikaži oznake con",
        "dividers":      "Notranje črte grelca",
        "style":         "🎨 Slog",
        "stroke_col":    "Barva linij",
        "bg_col":        "Barva ozadja",
        "inact_col":     "Barva križa (neaktivno)",
        "font_sz":       "Velikost pisave terminalov",
        "num_scheme":    "Shema številčenja terminalov",
        "seq_label":     "Zaporedno (1-2, 3-4 … grelec; 13-14 … TC)",
        "custom_label":  "Po meri (ročni vnos)",
        "per_zone":      "Konfiguracija po conah",
        "zone_hdr":      "Cona",
        "active_lbl":    "Aktivna",
        "wattage_lbl":   "Moč",
        "wattage_def":   "350 W",
        "zone_type_lbl": "Tip cone",
        "type_nozzle":   "VSTOPNA SOBA",   # without Š for laser compat
        "type_block":    "GRELNI BLOK",
        "type_heater":   "GRELEC",
        "warn_nozzle":   "⚠️ VSTOPNA ŠOBA je že dodeljena coni {z}. Samo ena je dovoljena.",
        "warn_block":    "⚠️ GRELNI BLOK je že dodeljen coni {z}. Samo eden je dovoljen.",
        "h_plus":        "G+",
        "h_minus":       "G−",
        "tc_plus":       "TC+",
        "tc_minus":      "TC−",
        "preview":       "Predogled",
        "download":      "⬇️  Prenesi SVG",
        "tip":           "Nasvet: odprite SVG v Inkscape ali brskalniku za urejanje.",
        "type_nozzle_svg": "VSTOPNA SOBA",
        "type_block_svg":  "GRELNI BLOK",
        "type_heater_svg": "GRELEC",
    },
    "EN": {
        "app_title":     "🔌 ARBURG Zone Diagram Generator",
        "app_sub":       "Configure heating zones and export as SVG.",
        "general":       "⚙️ General Settings",
        "diag_title":    "Diagram title",
        "num_zones":     "Number of zones",
        "zone_width":    "Zone width (px)",
        "svg_height":    "Diagram height (px)",
        "symbol":        "📐 Symbol Settings",
        "show_pol":      "Show +/− polarity labels",
        "show_zlbl":     "Show zone labels",
        "dividers":      "Heater internal dividers",
        "style":         "🎨 Style",
        "stroke_col":    "Line / stroke color",
        "bg_col":        "Background color",
        "inact_col":     "Inactive cross color",
        "font_sz":       "Terminal number font size",
        "num_scheme":    "Terminal numbering scheme",
        "seq_label":     "Sequential pairs (1-2, 3-4 … heater; 13-14 … TC)",
        "custom_label":  "Custom (enter manually)",
        "per_zone":      "Per-zone configuration",
        "zone_hdr":      "Zone",
        "active_lbl":    "Active",
        "wattage_lbl":   "Wattage",
        "wattage_def":   "350 W",
        "zone_type_lbl": "Zone type",
        "type_nozzle":   "NOZZLE",
        "type_block":    "HEATING BLOCK",
        "type_heater":   "HEATER",
        "warn_nozzle":   "⚠️ NOZZLE already assigned to zone {z}. Only one allowed.",
        "warn_block":    "⚠️ HEATING BLOCK already assigned to zone {z}. Only one allowed.",
        "h_plus":        "H+",
        "h_minus":       "H−",
        "tc_plus":       "TC+",
        "tc_minus":      "TC−",
        "preview":       "Preview",
        "download":      "⬇️  Download SVG",
        "tip":           "Tip: open the SVG in Inkscape or a browser for further editing.",
        "type_nozzle_svg": "NOZZLE",
        "type_block_svg":  "HEATING BLOCK",
        "type_heater_svg": "HEATER",
    },
}

# ─── Page setup ───────────────────────────────────────────────────────────────
st.set_page_config(page_title="ARBURG Zone Diagram Generator", layout="wide")

with st.sidebar:
    lang_choice = st.selectbox("🌐 Jezik / Language", ["SL", "EN"], index=0)

T = LANG[lang_choice]

st.title(T["app_title"])
st.markdown(T["app_sub"])

# ─── Sidebar config ───────────────────────────────────────────────────────────
with st.sidebar:
    st.header(T["general"])
    title_text      = st.text_input(T["diag_title"], value="ARBURG")
    num_zones       = st.slider(T["num_zones"], 1, 12, 6)
    zone_width      = st.slider(T["zone_width"], 180, 320, 256)
    svg_height      = st.slider(T["svg_height"], 400, 800, 580)

    st.markdown("---")
    st.header(T["symbol"])
    show_polarity   = st.checkbox(T["show_pol"], value=True)
    show_zone_lbl   = st.checkbox(T["show_zlbl"], value=True)
    heater_dividers = st.slider(T["dividers"], 0, 5, 3)

    st.markdown("---")
    st.header(T["style"])
    stroke_color    = st.color_picker(T["stroke_col"],  value="#444444")
    bg_color        = st.color_picker(T["bg_col"],      value="#ffffff")
    inactive_color  = st.color_picker(T["inact_col"],   value="#cc0000")
    font_size_num   = st.slider(T["font_sz"], 14, 36, 24)

# ─── Terminal numbering scheme ────────────────────────────────────────────────
st.subheader(T["num_scheme"])
num_scheme = st.radio("", [T["seq_label"], T["custom_label"]],
                      horizontal=True, label_visibility="collapsed")

# ─── Per-zone config ──────────────────────────────────────────────────────────
st.subheader(T["per_zone"])

ZONE_TYPES = [T["type_nozzle"], T["type_block"], T["type_heater"]]

zone_configs       = []
nozzle_assigned_to = None
block_assigned_to  = None
heater_counter     = 0

cols_per_row = min(num_zones, 6)
rows_needed  = (num_zones + cols_per_row - 1) // cols_per_row
col_sets     = [st.columns(cols_per_row) for _ in range(rows_needed)]

for z in range(num_zones):
    row = z // cols_per_row
    col_i = z % cols_per_row
    with col_sets[row][col_i]:
        st.markdown(f"**{T['zone_hdr']} {z+1}**")

        zone_type = st.selectbox(T["zone_type_lbl"], ZONE_TYPES,
                                 index=2, key=f"ztype{z}")

        if zone_type == T["type_nozzle"]:
            if nozzle_assigned_to is not None:
                st.warning(T["warn_nozzle"].format(z=nozzle_assigned_to))
            else:
                nozzle_assigned_to = z + 1
        elif zone_type == T["type_block"]:
            if block_assigned_to is not None:
                st.warning(T["warn_block"].format(z=block_assigned_to))
            else:
                block_assigned_to = z + 1

        if zone_type == T["type_nozzle"]:
            svg_label = T["type_nozzle_svg"]
        elif zone_type == T["type_block"]:
            svg_label = T["type_block_svg"]
        else:
            heater_counter += 1
            svg_label = f"{T['type_heater_svg']} {heater_counter}"

        active  = st.checkbox(T["active_lbl"], value=True, key=f"act{z}")
        wattage = ""
        if active:
            wattage = st.text_input(T["wattage_lbl"], value=T["wattage_def"], key=f"wat{z}")

        if num_scheme == T["custom_label"]:
            h_top = st.number_input(T["h_plus"],  value=z*2+1,             key=f"ht{z}", step=1)
            h_bot = st.number_input(T["h_minus"], value=z*2+2,             key=f"hb{z}", step=1)
            t_top = st.number_input(T["tc_plus"], value=z*2+1+num_zones*2, key=f"tt{z}", step=1)
            t_bot = st.number_input(T["tc_minus"],value=z*2+2+num_zones*2, key=f"tb{z}", step=1)
            zone_configs.append((int(h_top), int(h_bot), int(t_top), int(t_bot),
                                  svg_label, active, wattage))
        else:
            zone_configs.append((
                z*2+1, z*2+2,
                z*2+1+num_zones*2, z*2+2+num_zones*2,
                svg_label, active, wattage
            ))


# ─── SVG generation (no <text> — all paths) ──────────────────────────────────
def generate_svg(zones, title, zone_w, svg_h,
                 stroke, bg, inactive_col, font_num,
                 show_pol, show_zlbl, dividers):

    svg_w = zone_w * len(zones) + 4

    H_CX  = zone_w * 30 // 100
    T_CX  = zone_w * 70 // 100
    TOP_Y = int(svg_h * 0.145)
    BOT_Y = int(svg_h * 0.852)
    CR    = int(zone_w * 0.125)

    HR_TOP = int(svg_h * 0.232)
    HR_H   = int(svg_h * 0.483)
    HR_W   = int(zone_w * 0.226)
    HR_X   = H_CX - HR_W // 2

    chevron_top = int(svg_h * 0.396)
    chevron_bot = int(svg_h * 0.672)
    junc_y      = (chevron_top + chevron_bot) // 2
    tip_dx      = int(zone_w * 0.109)

    CROSS_PAD_X = int(zone_w * 0.06)
    CROSS_TOP   = int(svg_h * 0.10)
    CROSS_BOT   = int(svg_h * 0.90)

    fs_num   = font_num
    fs_title = int(svg_h * 0.076)
    fs_lbl   = int(svg_h * 0.029)
    fs_pol   = int(svg_h * 0.033)

    L = []
    L.append(f'<svg xmlns="http://www.w3.org/2000/svg" '
             f'viewBox="0 0 {svg_w} {svg_h}" '
             f'width="{svg_w}" height="{svg_h}" '
             f'style="background:{bg}">')
    L.append(f'<defs><style>'
             f'line,polyline{{stroke:{stroke};fill:none;stroke-width:1.8;}}'
             f'rect.heater{{fill:{bg};stroke:{stroke};stroke-width:1.8;}}'
             f'circle.terminal{{fill:{bg};stroke:{stroke};stroke-width:1.8;}}'
             f'circle.junc{{fill:{bg};stroke:{stroke};stroke-width:1.8;}}'
             f'.cross{{stroke:{inactive_col};stroke-width:4;stroke-linecap:round;opacity:0.85;}}'
             f'</style></defs>')

    # Title — path
    L.append(tp(title, svg_w // 2, int(svg_h * 0.048), fs_title, 'middle', stroke))

    for i, (t1, t2, t3, t4, zlabel, active, wattage) in enumerate(zones):
        ox  = i * zone_w + 2
        hx  = ox + H_CX
        tx  = ox + T_CX
        mid = ox + (H_CX + T_CX) // 2

        # Separator
        if i > 0:
            L.append(f'<line x1="{ox-2}" y1="0" x2="{ox-2}" y2="{svg_h}" '
                     f'stroke="{stroke}" stroke-width="1.5"/>')

        # ── Heater ──
        L.append(f'<circle cx="{hx}" cy="{TOP_Y}" r="{CR}" class="terminal"/>')
        L.append(tp(str(t1), hx, TOP_Y, fs_num, 'middle', stroke))
        L.append(f'<line x1="{hx}" y1="{TOP_Y+CR}" x2="{hx}" y2="{HR_TOP}"/>')
        L.append(f'<rect x="{ox+HR_X}" y="{HR_TOP}" width="{HR_W}" height="{HR_H}" class="heater"/>')
        if dividers > 0:
            step = HR_H / (dividers + 1)
            for d in range(1, dividers + 1):
                dy = int(HR_TOP + step * d)
                L.append(f'<line x1="{ox+HR_X+4}" y1="{dy}" x2="{ox+HR_X+HR_W-4}" y2="{dy}"/>')
        L.append(f'<line x1="{hx}" y1="{HR_TOP+HR_H}" x2="{hx}" y2="{BOT_Y-CR}"/>')
        L.append(f'<circle cx="{hx}" cy="{BOT_Y}" r="{CR}" class="terminal"/>')
        L.append(tp(str(t2), hx, BOT_Y, fs_num, 'middle', stroke))

        # ── Thermocouple ──
        L.append(f'<circle cx="{tx}" cy="{TOP_Y}" r="{CR}" class="terminal"/>')
        L.append(tp(str(t3), tx, TOP_Y, fs_num, 'middle', stroke))
        if show_pol:
            L.append(tp('+', tx + CR // 2 + fs_pol // 2, int(svg_h * 0.270), fs_pol, 'start', stroke))
        L.append(f'<line x1="{tx}" y1="{TOP_Y+CR}" x2="{tx}" y2="{chevron_top}"/>')
        tip_x = tx + tip_dx
        L.append(f'<polyline points="{tx},{chevron_top} {tip_x},{junc_y}"/>')
        L.append(f'<circle cx="{tip_x}" cy="{junc_y}" r="{max(5,int(zone_w*0.027))}" class="junc"/>')
        L.append(f'<polyline points="{tip_x},{junc_y} {tx},{chevron_bot}"/>')
        L.append(f'<line x1="{tx}" y1="{chevron_bot}" x2="{tx}" y2="{BOT_Y-CR}"/>')
        if show_pol:
            L.append(tp('-', tx + CR // 2 + fs_pol // 2, int(svg_h * 0.724), fs_pol, 'start', stroke))
        L.append(f'<circle cx="{tx}" cy="{BOT_Y}" r="{CR}" class="terminal"/>')
        L.append(tp(str(t4), tx, BOT_Y, fs_num, 'middle', stroke))

        # ── Inactive cross ──
        if not active:
            x0 = ox + CROSS_PAD_X
            x1 = ox + zone_w - CROSS_PAD_X
            L.append(f'<line x1="{x0}" y1="{CROSS_TOP}" x2="{x1}" y2="{CROSS_BOT}" class="cross"/>')
            L.append(f'<line x1="{x1}" y1="{CROSS_TOP}" x2="{x0}" y2="{CROSS_BOT}" class="cross"/>')

        # ── Zone label + wattage (only when active) ──
        if show_zlbl and active:
            L.append(tp(zlabel, mid, int(svg_h * 0.950), fs_lbl, 'middle', stroke))
        if active and wattage.strip():
            L.append(tp(wattage, mid, int(svg_h * 0.985), fs_lbl, 'middle', stroke))

    L.append('</svg>')
    return '\n'.join(L)


# ─── Preview & download ───────────────────────────────────────────────────────
svg_str = generate_svg(
    zone_configs, title_text, zone_width, svg_height,
    stroke_color, bg_color, inactive_color, font_size_num,
    show_polarity, show_zone_lbl, heater_dividers
)

st.markdown("---")
st.subheader(T["preview"])
st.components.v1.html(
    f'<div style="overflow-x:auto;background:#e0e0e0;padding:12px;border-radius:8px">'
    f'{svg_str}</div>',
    height=svg_height + 40,
    scrolling=True
)

st.download_button(
    label=T["download"],
    data=svg_str.encode("utf-8"),
    file_name=f"{title_text.replace(' ','_')}_zones.svg",
    mime="image/svg+xml",
    use_container_width=True,
)

st.caption(T["tip"])