include(Resources.id("mtrsteamloco:scripts/display_helper.js"));
importPackage(java.awt);
importPackage(java.awt.geom);
importPackage(java.awt.image);

//////////////////////////////
// 96x48 (LEDドット) キャンバスを state に確保
// 出力は 480x240（NEAREST拡大）
//////////////////////////////
function ensureHeadLedCanvas(state) {
    if (state.headLedW == null) state.headLedW = 96;
    if (state.headLedH == null) state.headLedH = 48;

    if (state.head_led_image == null
        || state.head_led_image.getWidth() != state.headLedW
        || state.head_led_image.getHeight() != state.headLedH) {

        state.head_led_image = new BufferedImage(state.headLedW, state.headLedH, BufferedImage.TYPE_INT_ARGB);
        state.head_led_g = state.head_led_image.createGraphics();

        // LEDっぽく：AA OFF
        state.head_led_g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
        state.head_led_g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
        state.head_led_g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
        state.head_led_g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
    }

    // ★字体は ikisaki（側面）に合わせる
    if (!state.fontJP) state.fontJP = Resources.readFont(Resources.id("mtr:fonts/notosanscjkjp-medium.otf"));
    if (!state.fontEN) state.fontEN = Resources.readFont(Resources.id("mtr:fonts/morio_s.ttf"));
}

//////////////////////////////
// 横幅に収めて中央（必要ならX方向圧縮）
// allowTrackingShort=true のとき 2〜3文字は字間を少し開ける
//////////////////////////////
function drawTrackingCentered(g2, text, baseFont, sizePx, x, yBaseline, w, color, maxExtraPerGapPx) {
    if (text == null) return;
    text = String(text);

    let font = baseFont.deriveFont(Font.PLAIN, sizePx);
    let fm = g2.getFontMetrics(font);
    let textW = fm.stringWidth(text);

    g2.setFont(font);
    g2.setColor(color);

    if (text.length <= 1) {
        g2.drawString(text, x + (w - textW) / 2, yBaseline);
        return;
    }

    let extra = w - textW;
    if (extra > 0 && text.length >= 2 && text.length <= 3) {
        let gaps = text.length - 1;
        let add = extra / gaps;
        if (maxExtraPerGapPx != null) add = Math.min(add, maxExtraPerGapPx);

        let totalW = textW + add * gaps;
        let cx = x + (w - totalW) / 2;

        for (let i = 0; i < text.length; i++) {
            let ch = text.substring(i, i + 1);
            g2.drawString(ch, cx, yBaseline);
            cx += fm.stringWidth(ch);
            if (i != text.length - 1) cx += add;
        }
        return;
    }

    g2.drawString(text, x + (w - textW) / 2, yBaseline);
}

function drawFitXCentered(g2, text, baseFont, sizePx, x, yBaseline, w, color, allowTrackingShort) {
    if (text == null) return;
    text = String(text);

    let font = baseFont.deriveFont(Font.PLAIN, sizePx);
    let fm = g2.getFontMetrics(font);
    let tw = fm.stringWidth(text);

    // 短いときは字間を少し開ける
    if (allowTrackingShort && tw < w && text.length >= 2 && text.length <= 3) {
        drawTrackingCentered(g2, text, baseFont, sizePx, x, yBaseline, w, color, 3.0);
        return;
    }

    // 収まるなら普通に中央
    if (tw <= w) {
        g2.setFont(font);
        g2.setColor(color);
        g2.drawString(text, x + (w - tw) / 2, yBaseline);
        return;
    }

    // X方向だけ圧縮
    let scaleX = w / tw;
    let at = new AffineTransform();
    at.scale(scaleX, 1.0);
    let scaledFont = font.deriveFont(at);

    let startX = x + (w - tw * scaleX) / 2;

    g2.setFont(scaledFont);
    g2.setColor(color);
    g2.drawString(text, startX / scaleX, yBaseline);
}

// 1文字を「centerX」を中心に描く（必要ならX圧縮）
function drawCharAtCenter(g2, ch, baseFont, sizePx, centerX, yBaseline, cellW, color) {
    let x = Math.round(centerX - cellW / 2);
    drawFitXCentered(g2, ch, baseFont, sizePx, x, yBaseline, cellW, color, true);
}

//////////////////////////////
// ★端固定（2〜5文字）／6文字以上は全体圧縮
// - totalW: sw(=96)
// - maxLen: 5 推奨
//////////////////////////////
function drawFixedEndsOrFit(g2, text, baseFont, sizePx, yBaseline, totalW, color, maxLen) {
    if (text == null) return;
    text = String(text);

    let len = text.length;
    if (maxLen == null) maxLen = 5;

    // 0-1文字：普通に中央
    if (len <= 1) {
        drawFitXCentered(g2, text, baseFont, sizePx, 0, yBaseline, totalW, color, true);
        return;
    }

    // ★6文字以上：全体圧縮で中央（重なり防止）
    if (len > maxLen) {
        drawFitXCentered(g2, text, baseFont, sizePx, 0, yBaseline, totalW, color, false);
        return;
    }

    // 2文字時の端位置を固定（96幅なら 12 と 84）
    let xL = totalW * 0.125;
    let xR = totalW * 0.875;

    // 1文字ずつ描くセル幅（48が安定）
    let cellW = totalW / 2;

    // ★端固定＆等間隔
    let step = (xR - xL) / (len - 1);

    for (let i = 0; i < len; i++) {
        let cx = xL + step * i;
        drawCharAtCenter(g2, text.substring(i, i + 1), baseFont, sizePx, cx, yBaseline, cellW, color);
    }
}

//////////////////////////////
// 種別カラーDB（JSON）ロード
//////////////////////////////
function loadRouteTypeColorDbOnce(state) {
    if (state.routeTypeColorDb != null) return;

    // ★側面と同じJSONを使う（必要ならここだけ変更）
    let path = "mtr:botapinu_lcd/mctq_pinu_lcd/route_type_colors.json";

    try {
        let txt = Resources.readString(Resources.id(path));
        state.routeTypeColorDb = JSON.parse(String(txt));
        if (state.routeTypeColorDb == null || typeof state.routeTypeColorDb !== "object") state.routeTypeColorDb = {};
        print("route_type_colors.json loaded (head): " + path);
    } catch (e) {
        state.routeTypeColorDb = {};
        print("FAILED route_type_colors.json (head): " + e);
    }
}

function parseAnyColor(v) {
    if (v == null) return null;

    // "Color.red" みたいな指定
    if (typeof v === "string" && v.startsWith("Color.")) {
        let name = v.substring(6);
        if (Color[name] != null) return Color[name];
    }

    // number
    if (typeof v === "number") {
        return new Color((v | 0), true);
    }

    let s = String(v).trim();
    if (s.length == 0) return null;

    // 0x....
    if (s.startsWith("0x") || s.startsWith("0X")) {
        let n = (java.lang.Long.parseLong(s.substring(2), 16)) | 0;
        return new Color(n, true);
    }

    // #....
    if (s.startsWith("#")) {
        let hex = s.substring(1);
        if (hex.length === 6) {
            let n = (java.lang.Integer.parseInt(hex, 16)) | 0;
            return new Color(n);
        } else if (hex.length === 8) {
            let n = (java.lang.Long.parseLong(hex, 16)) | 0;
            return new Color(n, true);
        }
    }

    // fallback: 数字文字列
    try {
        let n2 = (java.lang.Integer.parseInt(s)) | 0;
        return new Color(n2, true);
    } catch (e) { }

    return null;
}

function getRouteTypeColorOverride(state, routeTypeJpn) {
    loadRouteTypeColorDbOnce(state);
    if (!routeTypeJpn) return null;

    let key = String(routeTypeJpn).trim();
    let obj = state.routeTypeColorDb ? state.routeTypeColorDb[key] : null;
    if (!obj || typeof obj !== "object") return null;

    let bg = parseAnyColor(obj.bg);
    let fg = parseAnyColor(obj.fg);

    if (bg == null && fg == null) return null;
    return { bg: bg, fg: fg };
}


//////////////////////////////
// ★前面LED（Head）本体
//////////////////////////////
function ikisakiHead(g, state, train) {
    ensureHeadLedCanvas(state);

    let text_g = state.head_led_g;
    let sw = state.headLedW; // 96
    let sh = state.headLedH; // 48

    // 出力解像度（モデル側）
    let outW = 480;
    let outH = 240;

    // 色
    let backGround = new Color(0.188, 0.188, 0.188);
    let bg = new Color(0.08, 0.08, 0.08);
    let textColor = Color.white;

    // レイアウト
    let bandH = 24; // 上半分

    // サイズ（あなたの現状寄せ）
    let bigJP = 16;
    let midEN = 12;
    let bigDestJP = 16;
    let destEnSize = 12;

    // 位置（必要ならここだけ調整）
    let typeJpY = 14;
    let typeEnY = 24;
    let destJpY = 38;
    let destEnY = 47; // 48だと切れやすいので47推奨

    // platform 安全
    let platformList = train.getThisRoutePlatforms();
    let next = train.getThisRoutePlatformsNextIndex();
    let invalid = (platformList == null || platformList.length == 0 || next < 0 || next >= platformList.length);

    // デフォルト（2段表示扱い）
    let typeJP = "回送";
    let typeEN = "Not In Service";
    let destJP = "";
    let destEN = "";
    let routeColor = backGround;

    if (!invalid) {
        let p = platformList[next];
        let finalSta = p.destinationName;
        let routeType = p.route.lightRailRouteNumber;

        let rawTypeJP = TextUtil.getCjkParts(routeType);
        let rawTypeEN = TextUtil.getNonCjkParts(routeType);
        let rawDestJP = TextUtil.getCjkParts(finalSta);
        let rawDestEN = TextUtil.getNonCjkParts(finalSta);

        // 通常は routeColor を使う
        routeColor = new Color(p.route.color);

        let ov = getRouteTypeColorOverride(state, rawTypeJP);
        if (ov && ov.bg != null) {
            routeColor = ov.bg;
        }
        if (ov && ov.fg != null) {
            textColor = ov.fg;
        }

        // 2段表示扱い（行先は出さない）
        if (!train.isOnRoute() || rawTypeJP == "回送" || rawDestJP == "回送") {
            typeJP = "回送"; typeEN = "Not In Service";
            destJP = ""; destEN = "";
            routeColor = backGround;

        } else if (rawTypeJP == "試運転" || rawDestJP == "試運転") {
            typeJP = "試運転"; typeEN = "Test Run";
            destJP = ""; destEN = "";
            routeColor = backGround;

        } else if (rawDestJP == "臨時" || rawTypeJP == "臨時") {
            typeJP = "臨時"; typeEN = "Extra";
            destJP = ""; destEN = "";
            routeColor = backGround;

        } else if (rawDestJP == "団体専用" || rawTypeJP == "団体専用") {
            typeJP = "団体専用"; typeEN = "Group";
            destJP = ""; destEN = "";
            routeColor = backGround;

        } else {
            // 通常運用（4段）
            typeJP = rawTypeJP;
            typeEN = rawTypeEN;
            destJP = rawDestJP;
            destEN = rawDestEN;
        }
    }

    // まず全消去
    text_g.setColor(bg);
    text_g.fillRect(0, 0, sw, sh);

    // ---------------------------------------
    // 2段表示（回送/試運転/臨時/団体）
    // ---------------------------------------
    if (destJP == "" && destEN == "") {
        text_g.setColor(backGround);
        text_g.fillRect(0, 0, sw, sh);

        drawFitXCentered(text_g, String(typeJP), state.fontJP, 24, 0, 28, sw, Color.white, true);
        drawFitXCentered(text_g, String(typeEN), state.fontEN, 12, 0, 44, sw, Color.white, false);

    } else {
        // ---------------------------------------
        // 通常運用（4段）：上帯 routeColor
        // ---------------------------------------
        text_g.setColor(bg);
        text_g.fillRect(0, 0, sw, sh);

        text_g.setColor(routeColor);
        text_g.fillRect(0, 0, sw, bandH);

        // ★端固定（2〜5文字）/ 6文字以上は圧縮
        drawFixedEndsOrFit(text_g, String(typeJP), state.fontJP, bigJP, typeJpY, sw, textColor, 5);
        drawFitXCentered(text_g, String(typeEN), state.fontEN, midEN, 0, typeEnY, sw, textColor, false);

        drawFixedEndsOrFit(text_g, String(destJP), state.fontJP, bigDestJP, destJpY, sw, textColor, 5);
        drawFitXCentered(text_g, String(destEN), state.fontEN, destEnSize, 0, destEnY, sw, textColor, false);
    }

    // 96x48 → 480x240（ドット拡大）
    if (g instanceof java.awt.Graphics2D) {
        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
        g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
    }
    let ledImageFront = Resources.readBufferedImage(Resources.id("mtr:botapinu_lcd/mctq_pinu_lcd/images/led_front.png"));
    g.drawImage(state.head_led_image, 0, 0, outW, outH, 0, 0, sw, sh, null);
    g.drawImage(ledImageFront, 0, 0, outW + 1, outH + 1, null);
}