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

importPackage(java.lang);
importPackage(java.util.concurrent);

let slotCfg = {
    "version": 1,
    "texSize": [400, 100],
    "slots": [{
        "name": "main",
        "texArea": [0, 0, 400, 100],
        "pos": [[[ -1.5, 1, 0 ], [ -1.5, 0, 0 ], [ 2.5, 0, 0 ], [ 2.5, 1, 0 ]]],
        "offsets": [[0.01, 0, 0]]
    }]
};
let dhBase = new DisplayHelper(slotCfg);
let activeLCDs = [];
let asyncPool = null;

function create(ctx, state, blockEntity) {
    state.dh = dhBase.create();
    state.font = Resources.readFont(Resources.id("mtrsteamloco:eyecandies/font/dotgothic.ttf"));
    state.hassyahyo = Resources.readBufferedImage(Resources.id("mtrsteamloco:eyecandies/hassyahyo/hassyahyo.png"));
    state.hassyahyo_alpha = Resources.readBufferedImage(Resources.id("mtrsteamloco:eyecandies/hassyahyo/hassyahyo_alpha.png"));
    activeLCDs.push({ ctx: ctx, state: state, blockEntity: blockEntity });

    if (Resources.ANTE_FLAG && asyncPool === null) {
        asyncPool = Executors.newScheduledThreadPool(1);

        // メイン描画
        asyncPool.scheduleAtFixedRate(new java.lang.Runnable({
            run: function () {
                for (let i = 0; i < activeLCDs.length; i++) {
                    let entry = activeLCDs[i];
                    if (!entry.state.dh || entry.state.dh.closed) continue;
                    try {
                        tick(entry.ctx, entry.state, entry.blockEntity);
                        entry.ctx.drawCalls.put(i, new ClusterDrawCall(entry.state.dh.model, new Matrix4f()));
                    } catch (e) {
                        print("描画中に例外が発生しました: " + e);
                    }
                }
            }
        }), 0, 1000 / 2, TimeUnit.MILLISECONDS);

        // 遅延情報の定期取得
        asyncPool.scheduleAtFixedRate(new java.lang.Runnable({
            run: function () {
                fetchDelaysFromURL(function (json) {
                    let delayMsgs = generateDelayMessages(json);
                    for (let i = 0; i < activeLCDs.length; i++) {
                        activeLCDs[i].state.delayMessages = delayMsgs;
                    }
                });
            }
        }), 0, 30, TimeUnit.SECONDS);
    }
}

function dispose(ctx, state, blockEntity) {
    for (let i = activeLCDs.length - 1; i >= 0; i--) {
        if (activeLCDs[i].blockEntity.equals(blockEntity)) {
            activeLCDs.splice(i, 1);
            break;
        }
    }
    if (activeLCDs.length === 0 && asyncPool !== null) {
        asyncPool.shutdown();
        asyncPool = null;
    }
    state.dh.close();
}

function use(ctx, state, blockEntity, player) {
    let thisPos = blockEntity.getWorldPosVector3f();
    let station = MinecraftClient.getStationAt(thisPos);
    let platformMap = station
        ? MTRClientData.DATA_CACHE.requestStationIdToPlatforms(station.id)
        : new java.util.HashMap();

    let platformIds = Array.from(platformMap.keySet());

    let configValues = {};
    for (let i = 0; i < platformIds.length; i++) {
        let idLong = platformIds[i];
        let id = idLong.longValue();
        let key = "platform_" + id;
        let savedValue = blockEntity.getCustomConfig(key);
        let parsedValue = String(savedValue).toLowerCase() === "true";
        configValues[key] = parsedValue;
    }

    blockEntity.registerCustomConfig({
        getKeys: function () {
            return Object.keys(configValues);
        },
        respond: function (key) {
            return configValues[key] ? "true" : "false";
        }
    });

    let builder = IScreen.ClothConfig2.createConfigBuilder();
    builder.setTitle(ComponentUtil.literal("ホーム選択"));
    let category = builder.getOrCreateCategory(ComponentUtil.literal("プラットフォーム"));
    let entryBuilder = builder.entryBuilder();

    for (let i = 0; i < platformIds.length; i++) {
        let idLong = platformIds[i];
        let id = idLong.longValue();
        let platform = platformMap.get(idLong);
        let name = platform.name;
        let key = "platform_" + id;

        let initialValue = configValues[key];
        let toggleEntry = entryBuilder
            .startBooleanToggle(ComponentUtil.literal(name), initialValue)
            .setDefaultValue(initialValue)
            .setSaveConsumer(function (value) {
                configValues[key] = value;
            });
        category.addEntry(toggleEntry.build());
    }

    builder.setSavingRunnable(function () {
        for (let key in configValues) {
            let valueStr = configValues[key] ? "true" : "false";
            blockEntity.putCustomConfig(key, valueStr);
        }
        blockEntity.registerCustomConfig({
            getKeys: function () {
                return Object.keys(configValues);
            },
            respond: function (key) {
                return configValues[key] ? "true" : "false";
            }
        });
    });

    MinecraftClient.setScreen(builder.build());
}

function formatMinutesToHHMM(totalMinutes) {
    var hour = Math.floor(totalMinutes / 60);
    var minute = totalMinutes % 60;
    var hh = (hour < 10 ? "0" + hour : "" + hour);
    var mm = (minute < 10 ? "0" + minute : "" + minute);
    return hh + ":" + mm;
}

function getRouteById(routeId) {
    let routesSet = MTRClientData.ROUTES;
    let routesArray = routesSet.toArray();
    for (let i = 0; i < routesArray.length; i++) {
        if (routesArray[i].id === routeId) {
            return routesArray[i];
        }
    }
    return null;
}

function getStationByPlatformId(platformId) {
    let stations = MTRClientData.STATIONS.iterator();
    while (stations.hasNext()) {
        let station = stations.next();
        let platforms = MTRClientData.DATA_CACHE.requestStationIdToPlatforms(station.id);
        if (!platforms) continue;
        let keys = platforms.keySet().iterator();
        while (keys.hasNext()) {
            let pid = keys.next();
            if (pid.longValue() === platformId) {
                return station;
            }
        }
    }
    return null;
}

// == 遅延情報取得API ==
function fetchDelaysFromURL(callback) {
    try {
        let url = new URL("http://"); //system mapのURLに"/delays"を入れたものを書く,ホーム用も同様
        var con = url.openConnection();
        con.setRequestMethod("GET");
        con.setConnectTimeout(3000);
        con.setReadTimeout(5000);

        var reader = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
        var line;
        var response = "";
        while ((line = reader.readLine()) !== null) {
            response += line;
        }
        reader.close();

        var parsedJson = JSON.parse(String(response));
        callback(parsedJson);
    } catch (e) {
        print("遅延情報の取得エラー: " + e);
    }
}

function generateDelayMessages(json) {
    var entries = [];
    for (var i = 0; i < json.length; i++) {
        var item = json[i];
        if (item instanceof Array) {
            entries = entries.concat(item);
        } else {
            entries.push(item);
        }
    }
    entries.sort(function(a, b) { return b.delay - a.delay; });

    var msgs = [];
    for (var i = 0; i < entries.length && msgs.length < 5; i++) {
        var delay_entry = entries[i];
        if (!delay_entry.delay || isNaN(delay_entry.delay)) continue;

        var delayM = Math.floor(delay_entry.delay / 1200);
        if (delayM === 0) continue;

        var name = delay_entry.name || "不明路線";
        var delay_destination = "？";
        if (delay_entry.destination && typeof delay_entry.destination === "string") {
            delay_destination = TextUtil.getCjkParts(delay_entry.destination.split("|")[0]);
        }
        var lineName = TextUtil.getCjkParts(name.replace(/\[.*?\]/g, "").trim());
        var message = "【" + lineName + " 遅延】" + lineName + "は、" + delay_destination + "行きに約" + delayM + "分の遅れが出ています。";
        msgs.push(message);
    }
    if (msgs.length === 0) {
        msgs.push("現在、各路線は平常運行です。");
    }
    return msgs;
}

function assyukuDraw(g,text,textSize,drawPos,width,font,textColor,xOffset){
    let nextStaScale = 1.0;
    // 文字の幅を測定
    if (g.getFontMetrics(font.deriveFont(Font.PLAIN, textSize)).stringWidth(text) > width) {
         nextStaScale = (width) / g.getFontMetrics(font.deriveFont(Font.PLAIN, textSize)).stringWidth(text);
    }
    // 描画
    g.setFont(font.deriveFont(AffineTransform.getScaleInstance(nextStaScale, 1.0)).deriveFont(Font.PLAIN, textSize));             
    g.setColor(textColor);
    g.drawString(text, xOffset, drawPos);
}

function tick(ctx, state, blockEntity) {
    g = state.dh.graphicsFor("main");
    g.drawImage(state.hassyahyo, 0, 0, 400, 100, null);

    // 選択プラットフォーム
    let selectedPlatformIds = [];
    let thisPos = blockEntity.getWorldPosVector3f();
    let station = MinecraftClient.getStationAt(thisPos);
    let platformMap = station
        ? MTRClientData.DATA_CACHE.requestStationIdToPlatforms(station.id)
        : new java.util.HashMap();
    let platformIds = Array.from(platformMap.keySet());
    for (let i = 0; i < platformIds.length; i++) {
        let idLong = platformIds[i];
        let id = idLong.longValue();
        let key = "platform_" + id;
        if (String(blockEntity.getCustomConfig(key)).toLowerCase() === "true") {
            selectedPlatformIds.push(idLong);
        }
    }

    // --- 停車列車（通過列車の除外: 「通過」ロジックは一切なし！）---
    let allTrains = [];
    for (let i = 0; i < selectedPlatformIds.length; i++) {
        let platformId = selectedPlatformIds[i];
        let schedules = MTRClientData.SCHEDULES_FOR_PLATFORM.get(platformId);
        if (!schedules) continue;

        let scheduleList = Array.from(schedules);
        scheduleList.sort(function(a, b) { return a.arrivalMillis - b.arrivalMillis; });
        for (let j = 0; j < scheduleList.length; j++) {
            let schedule = scheduleList[j];
            let platform = platformMap.get(platformId);
            let dwellTime = platform.dwellTime;
            let departureTimeMillis = schedule.arrivalMillis + dwellTime * 500;
            if (departureTimeMillis < Date.now() - 1000 * 60 * 60 * 24) {
                departureTimeMillis = Date.now() + departureTimeMillis;
            }
            allTrains.push({
                type: "停車",
                departureTimeMillis: departureTimeMillis,
                routeId: schedule.routeId,
                platformId: platformId,
                schedule: schedule
            });
        }
    }
    allTrains.sort(function(a, b) { return a.departureTimeMillis - b.departureTimeMillis; });

    // --- 描画処理（共通ロジック: 種別色分け/複数ホーム/略称）---
    let y = 30;
    const lineHeight = 60;

    // 最大5件まで
    for (let i = 0; i < allTrains.length && i < 5; i++) {
        let entry = allTrains[i];
        let route = getRouteById(entry.routeId);
        if (!route) continue;
        let routeType = route.lightRailRouteNumber.toString();
        let routeTypeJpn = TextUtil.getCjkParts(routeType).toString().trim();

        // 行き先名取得ロジック（ホーム用と同じ）
        var Dest;
        var customDest = null;
        try {
            customDest = route.getDestination(route.platformIds.size() - 1);
        } catch (e) { customDest = null; }
        if (customDest) {
            Dest = customDest;
        } else {
            var LastPlatLong = new java.lang.Long(route.getLastPlatformId());
            Dest = "？";
            var stationIter = MTRClientData.STATIONS.iterator();
            var seenStationIds = new java.util.HashSet();
            while (stationIter.hasNext()) {
                var st = stationIter.next();
                if (seenStationIds.contains(st.id)) continue;
                seenStationIds.add(st.id);
                var platformsMap = MTRClientData.DATA_CACHE.requestStationIdToPlatforms(st.id);
                if (platformsMap) {
                    var keyIter = platformsMap.keySet().iterator();
                    while (keyIter.hasNext()) {
                        var platLong = keyIter.next();
                        if (platLong.equals(LastPlatLong)) {
                            Dest = st.name;
                            break;
                        }
                    }
                }
                if (Dest !== "？") break;
            }
        }

        let departureDate = new Date(entry.departureTimeMillis);
        let hh = departureDate.getHours();
        let mm = departureDate.getMinutes();
        let timeStr = (hh < 10 ? "0" + hh : hh) + ":" + (mm < 10 ? "0" + mm : mm);

        g.setFont(state.font.deriveFont(Font.PLAIN, 25));
        g.setColor(Color.white);
        g.drawString(timeStr, 80, y);

        // ラベル類
        g.setFont(state.font.deriveFont(Font.PLAIN, 25));
        g.setColor(y === 30 ? Color.orange : Color.white);
        g.drawString(y === 30 ? "先発" : "次発", 5, y);

        // 種別表示（ホーム版と構造・色分け統一）
        if (Date.now() % 20000 < 10000) {
            if (routeTypeJpn == "普通") {
                g.setColor(Color.lightGray);
                g.fillRect(150, y - 25, g.getFontMetrics(state.font.deriveFont(Font.PLAIN, 25)).stringWidth(TextUtil.getCjkParts(routeType)), 30);
                g.setColor(Color.white);
                g.drawString(TextUtil.getCjkParts(routeType), 150, y);
            } else if (routeTypeJpn == "快速") {
                g.setColor(Color.red);
                g.fillRect(150, y - 25, g.getFontMetrics(state.font.deriveFont(Font.PLAIN, 25)).stringWidth(TextUtil.getCjkParts(routeType)), 30);
                g.setColor(Color.white);
                g.drawString(TextUtil.getCjkParts(routeType), 150, y);
            } else if (routeTypeJpn == "区間快速") {
                g.setColor(Color.blue);
                g.fillRect(150, y - 25, g.getFontMetrics(state.font.deriveFont(Font.PLAIN, 25)).stringWidth("区快"), 30);
                g.setColor(Color.white);
                g.drawString("区快", 150, y);
            } else if (routeTypeJpn == "通勤快速") {
                g.setColor(Color.orange);
                g.fillRect(150, y - 25, g.getFontMetrics(state.font.deriveFont(Font.PLAIN, 25)).stringWidth("通快"), 30);
                g.setColor(Color.white);
                g.drawString("通快", 150, y);
            } else if (routeTypeJpn == "新快速") {
                g.setColor(Color.green);
                g.fillRect(150, y - 25, g.getFontMetrics(state.font.deriveFont(Font.PLAIN, 25)).stringWidth("新快"), 30);
                g.setColor(Color.white);
                g.drawString("新快", 150, y);
            } else if (routeTypeJpn == "各駅停車") {
                g.setColor(Color.cyan);
                g.fillRect(150, y - 25, g.getFontMetrics(state.font.deriveFont(Font.PLAIN, 25)).stringWidth("各停"), 30);
                g.setColor(Color.white);
                g.drawString("各停", 150, y);
            } else if (routeTypeJpn == "準急") {
                g.setColor(Color.green);
                g.fillRect(150, y - 25, g.getFontMetrics(state.font.deriveFont(Font.PLAIN, 25)).stringWidth(TextUtil.getCjkParts(routeType)), 30);
                g.setColor(Color.white);
                g.drawString(TextUtil.getCjkParts(routeType), 150, y);
            } else if (routeTypeJpn == "急行") {
                g.setColor(Color.red);
                g.fillRect(150, y - 25, g.getFontMetrics(state.font.deriveFont(Font.PLAIN, 25)).stringWidth(TextUtil.getCjkParts(routeType)), 30);
                g.setColor(Color.white);
                g.drawString(TextUtil.getCjkParts(routeType), 150, y);
            } else if (routeTypeJpn == "快速急行") {
                g.setColor(new Color(0.537, 0.0, 1.0));
                g.fillRect(150, y - 25, g.getFontMetrics(state.font.deriveFont(Font.PLAIN, 25)).stringWidth("快急"), 30);
                g.setColor(Color.white);
                g.drawString("快急", 150, y);
            } else {
                g.setColor(Color.white);
                g.drawString(TextUtil.getCjkParts(routeType), 150, y);
            }
            assyukuDraw(g,TextUtil.getCjkParts(Dest),25,y,150,state.font,Color.white,240);
        } else {
            if (routeTypeJpn == "普通") {
                g.setColor(Color.lightGray);
                g.fillRect(150, y - 25, g.getFontMetrics(state.font.deriveFont(Font.PLAIN, 25)).stringWidth(TextUtil.getNonCjkParts(routeType)), 30);
                g.setColor(Color.white);
                g.drawString(TextUtil.getNonCjkParts(routeType), 150, y);
            } else if (routeTypeJpn == "快速") {
                g.setColor(Color.red);
                g.fillRect(150, y - 25, g.getFontMetrics(state.font.deriveFont(Font.PLAIN, 25)).stringWidth(TextUtil.getNonCjkParts(routeType)), 30);
                g.setColor(Color.white);
                g.drawString(TextUtil.getNonCjkParts(routeType), 150, y);
            } else if (routeTypeJpn == "区間快速") {
                g.setColor(Color.blue);
                g.fillRect(150, y - 25, g.getFontMetrics(state.font.deriveFont(Font.PLAIN, 25)).stringWidth("区快"), 30);
                g.setFont(state.font.deriveFont(Font.PLAIN, 10));
                g.setColor(Color.white);
                g.drawString("Semi", 160, y - 15);
                g.drawString("Rapid", 160, y);
            } else if (routeTypeJpn == "通勤快速") {
                g.setColor(Color.orange);
                g.fillRect(150, y - 25, g.getFontMetrics(state.font.deriveFont(Font.PLAIN, 25)).stringWidth("通快"), 30);
                g.setFont(state.font.deriveFont(Font.PLAIN, 10));
                g.setColor(Color.white);
                g.drawString("Com.", 160, y - 15);
                g.drawString("Rapid", 160, y);
            } else if (routeTypeJpn == "新快速") {
                g.setColor(Color.green);
                g.fillRect(150, y - 25, g.getFontMetrics(state.font.deriveFont(Font.PLAIN, 25)).stringWidth("新快"), 30);
                g.setFont(state.font.deriveFont(Font.PLAIN, 10));
                g.setColor(Color.white);
                g.drawString("New", 160, y - 15);
                g.drawString("Rapid", 160, y);
            } else if (routeTypeJpn == "各駅停車") {
                g.setColor(Color.cyan);
                g.fillRect(150, y - 25, g.getFontMetrics(state.font.deriveFont(Font.PLAIN, 25)).stringWidth("各停"), 30);
                g.setColor(Color.white);
                g.drawString(TextUtil.getNonCjkParts(routeType), 150, y);
            } else if (routeTypeJpn == "準急") {
                g.setColor(Color.green);
                g.fillRect(150, y - 25, g.getFontMetrics(state.font.deriveFont(Font.PLAIN, 25)).stringWidth("準急"), 30);
                g.setFont(state.font.deriveFont(Font.PLAIN, 10));
                g.setColor(Color.white);
                g.drawString("Semi", 160, y - 15);
                g.drawString("Exp.", 160, y);
            } else if (routeTypeJpn == "急行") {
                g.setColor(Color.red);
                g.fillRect(150, y - 25, g.getFontMetrics(state.font.deriveFont(Font.PLAIN, 25)).stringWidth(TextUtil.getNonCjkParts(routeType)), 30);
                g.setColor(Color.white);
                g.drawString("Exp.", 150, y);
            } else if (routeTypeJpn == "快速急行") {
                g.setColor(new Color(0.537, 0.0, 1.0));
                g.fillRect(150, y - 25, g.getFontMetrics(state.font.deriveFont(Font.PLAIN, 25)).stringWidth("快急"), 30);
                g.setFont(state.font.deriveFont(Font.PLAIN, 10));
                g.setColor(Color.white);
                g.drawString("Rapid", 160, y - 15);
                g.drawString("Exp.", 160, y);
            } else {
                g.setColor(Color.white);
                g.drawString(TextUtil.getNonCjkParts(routeType), 150, y);
            }
            if (TextUtil.getNonCjkParts(Dest).includes("-")) {
                assyukuDraw(g,TextUtil.getNonCjkParts(Dest).split("-")[0] + "-",13,y-15,150,state.font,Color.white,240);
                assyukuDraw(g,TextUtil.getNonCjkParts(Dest).split("-")[1],13,y,150,state.font,Color.white,240);
            } else {
                assyukuDraw(g,TextUtil.getNonCjkParts(Dest),25,y,150,state.font,Color.white,240);
            }
        }
        y += lineHeight;
        if (y > 90) break;
    }

    // --- スクロールメッセージ（遅延情報＋駅案内 他）---
    let callingSta = [];
    if (selectedPlatformIds.length > 0) {
        let schedules0 = MTRClientData.SCHEDULES_FOR_PLATFORM.get(selectedPlatformIds[0]);
        if (schedules0 && schedules0.size() > 0) {
            let firstRouteId = schedules0.toArray()[0].routeId;
            let route1 = getRouteById(firstRouteId);

            for (let j = route1.getPlatformIdIndex(selectedPlatformIds[0]) + 1; j < route1.platformIds.size(); j++) {
                let platId = route1.platformIds.get(j).platformId;
                let st = getStationByPlatformId(platId);
                if (st) callingSta.push(TextUtil.getCjkParts(st.name));
            }
        }
    }
    let callingStaMsg = callingSta.length > 0 ? "停車駅:" + callingSta.join("、") : "";

    let baseMsgs = [
        "勝炭鉄道をご利用下さいまして、ありがとうございます。",
        "歩きスマホは大変危険です。おやめ下さいますよう、ご協力お願いします。",
        callingStaMsg
    ];

    let delayMsgs = (state.delayMessages && state.delayMessages.length > 0) ? state.delayMessages : [];
    let msgs = [];
    var max = Math.max(delayMsgs.length, baseMsgs.length);
    for (var i = 0; i < max; i++) {
        if (i < delayMsgs.length) msgs.push(delayMsgs[i]);
        if (i < baseMsgs.length) msgs.push(baseMsgs[i]);
    }

    if (state.messageIndex === undefined) state.messageIndex = 0;
    if (state.scrollOffset === undefined) state.scrollOffset = 300;

    let curMsg = msgs[state.messageIndex % msgs.length];
    let sf = state.font.deriveFont(Font.PLAIN, 25);
    g.setFont(sf);
    g.setColor(Color.yellow);
    g.drawString(curMsg, state.scrollOffset, 60);
    let w = g.getFontMetrics(sf).stringWidth(curMsg);

    state.scrollOffset -= 20;
    if (state.scrollOffset < -w) {
        state.scrollOffset = 300;
        state.messageIndex++;
    }

    g.drawImage(state.hassyahyo_alpha, 0, 0, 400, 100, null);
    state.dh.upload();
}

// ----- 通常通りの render -----
function render(ctx, state, blockEntity) {
    if (!Resources.ANTE_FLAG) {
        tick(ctx, state, blockEntity);
        ctx.drawModel(state.dh.model, null);
    }
}
