importPackage(java.awt);
importPackage(java.awt.geom);

include(Resources.id("mtrsteamloco:scripts/display_helper.js"));
include("draw_lcd.js");
// include("mtr_util.js");

var meetNTEVersionRequirement = Resources.getNTEVersionInt() >= 402;
var isMTR4 = Resources.getMTRVersion().includes("4.0");

var slotCfg = {
    "version": 1,
    "texSize": [
      3640.0,
      280.0
    ],
    "slots": [
      {
        "name": "lcd_door_left",
        "texArea": [
          0.0,
          0,
          1820.0,
          280.0
        ],
        "pos": [
          [
            [
              -0.7413982,
              2.4235707,
              -1.6869998
            ],
            [
              -0.806103,
              2.1820894,
              -1.6869998
            ],
            [
              -0.8061029,
              2.1820891,
              -3.3119998
            ],
            [
              -0.7413981,
              2.4235707,
              -3.3119998
            ]
          ]
        ],
        "offsets": [
          [
            0.0,
            0.0,
            0.0
          ],
          [
            0.0,
            0.0,
            5.0
          ],
          [
            0.0,
            0.0,
            10.0
          ],
          [
            0.0,
            0.0,
            -5.0
          ]
        ]
      },
      {
        "name": "lcd_door_right",
        "texArea": [
          1820.0,
          0,
          1820.0,
          280.0
        ],
        "pos": [
          [
            [
              0.7397038,
              2.4247175,
              -3.312
            ],
            [
              0.80440855,
              2.183236,
              -3.312
            ],
            [
              0.80440855,
              2.183236,
              -1.687
            ],
            [
              0.7397038,
              2.4247175,
              -1.687
            ]
          ]
        ],
        "offsets": [
          [
            0.0,
            0.0,
            0.0
          ],
          [
            0.0,
            0.0,
            5.0
          ],
          [
            0.0,
            0.0,
            10.0
          ],
          [
            0.0,
            0.0,
            -5.0
          ]
        ]
      }
    ]
};

var dhBase = new DisplayHelper(slotCfg);

function create(ctx, state, train) {
    state.dh = dhBase.create();

    if (!meetNTEVersionRequirement || isMTR4) {
        let g = state.dh.graphicsFor("lcd_door_left");
        drawBlueScreen(g);

        g = state.dh.graphicsFor("lcd_door_right");
        drawBlueScreen(g);

        state.dh.upload();

        return;
    }

    state.leftPartUseCjkTracker = new CycleTracker([true, CONFIG.leftPartCjkCycle.cjk, false, CONFIG.leftPartCjkCycle.nonCjk]);
    
    // 初始化动画状态
    state.doorAnimationPhase = 0;
    state.stationNameTracker = new CycleTracker(["below", 2, "above", 2]);
    state.arrowAnimationFrame = 0;
    state.flashPhase = 0;
    state.routeMapType = "full";
}

function dispose(ctx, state, train) {
    state.dh.close();
}

function render(ctx, state, train) {
    for (let i = 0; i < train.trainCars(); i++) {
        ctx.drawCarModel(state.dh.model, i, null);
    }

    if (!meetNTEVersionRequirement || isMTR4) {
        return;
    }

    state.leftPartUseCjkTracker.tick();
    state.stationNameTracker.tick();
    
    if (state.rightPartScreenTypeTracker != null) {
        state.rightPartScreenTypeTracker.tick();
    }
    if (state.rightPartFullRouteMapUseCjkTracker != null) {
        state.rightPartFullRouteMapUseCjkTracker.tick();
    }
    
    // 全线/区间切换
    if (state.trainStatus == STATUS_ON_ROUTE) {
        if (!state.routeMapTracker) {
            state.routeMapTracker = new CycleTracker(["full", 5, "section", 10]);
        }
        state.routeMapTracker.tick();
        state.routeMapType = state.routeMapTracker.stateNow();
    }

    if (train.shouldRender() && train.shouldRenderDetail() && shouldRepaintLCD(state, train)) {
        if (state.trainStatus == STATUS_ARRIVED || state.trainStatus == STATUS_WAITING_FOR_DEPARTURE || state.trainStatus == STATUS_RETURNING_TO_DEPOT || state.trainStatus == STATUS_NO_ROUTE) { // 部分情况下右屏不切换。STATUS_ARRIVED: 只显示“已到达”屏幕；STATUS_WAITING_FOR_DEPARTURE: 只显示全线信息屏幕；STATUS_RETURNING_TO_DEPOT: 只显示“即将到达”屏幕；STATUS_NO_ROUTE: 只显示蓝屏。
            state.rightPartScreenTypeTracker = undefined;
        } else if (state.rightPartScreenTypeTracker == null) { // 否则，如果 state 中不存在 rightPartScreenTypeTracker，则初始化
            state.rightPartScreenTypeTracker = new CycleTracker([SCREEN_COMING_NEXT, CONFIG.rightPartScreenCycle.comingNext, SCREEN_FULL_ROUTE_MAP, CONFIG.rightPartScreenCycle.fullRouteMap, SCREEN_NEXT_TEXT, CONFIG.rightPartScreenCycle.nextText]);
            state.rightPartScreenTypeTracker.tick();
        }

        if ((state.rightPartScreenTypeTracker == null && state.trainStatus != STATUS_WAITING_FOR_DEPARTURE) || (state.rightPartScreenTypeTracker != null && state.rightPartScreenTypeTracker.stateNow() != SCREEN_FULL_ROUTE_MAP)) { // 如果右屏不切换（排除 STATUS_WAITING_FOR_DEPARTURE）或当前右屏不为全线线路图，不切换右屏 CJK。
            state.rightPartFullRouteMapUseCjkTracker = undefined;
        } else if (state.rightPartFullRouteMapUseCjkTracker == null) {
            state.rightPartFullRouteMapUseCjkTracker = new CycleTracker([true, CONFIG.fullRouteMapCjkCycle.cjk, false, CONFIG.fullRouteMapCjkCycle.nonCjk]);
            state.rightPartFullRouteMapUseCjkTracker.tick();
        }

        let platformInfo;
        switch (state.trainStatus) {
            case STATUS_NO_ROUTE:
                platformInfo = null;
                break;
            case STATUS_RETURNING_TO_DEPOT:
                platformInfo = train.getAllPlatforms().get(train.getAllPlatforms().size() - 1);
                break;
            case STATUS_WAITING_FOR_DEPARTURE:
                platformInfo = train.getAllPlatforms().get(0);
                break;
            case STATUS_CHANGING_ROUTE:
                platformInfo = train.getAllPlatforms().get(train.getAllPlatformsNextIndex());
                break;
            default:
                platformInfo = train.getThisRoutePlatforms().get(train.getThisRoutePlatformsNextIndex());
                break;
        }

        const routeInfo = getRouteInfo(train, state.trainStatus, platformInfo);
        if (!checkJsonProperty(state, "routeInfo", routeInfo)) { // 如果 state 中不存在 routeInfo 或 routeInfo 改变
            print("列车 " + train.id() + " 的当前路线信息：" + JSON.stringify(routeInfo));
            state.routeInfo = routeInfo;
        }

        const doorOpenInfo = CONFIG.showDoorOpenInfo ? getDoorOpenInfo(train) : undefined;
        if (CONFIG.showDoorOpenInfo && !checkJsonProperty(state, "doorOpenInfo", doorOpenInfo) && (state.trainStatus != STATUS_ARRIVED || train.isDoorOpening())) { // 如果 state 中不存在 doorOpenInfo 或 doorOpenInfo 改变
            print("列车 " + train.id() + " 的无法开门信息：" + JSON.stringify(doorOpenInfo));
            state.doorOpenInfo = doorOpenInfo;
        }
        
        // 获取列车开门方向（支持提前获取）
        const doorOpeningSide = getDoorOpeningSide(train);
        if (!checkJsonProperty(state, "doorOpeningSide", doorOpeningSide)) {
            print("列车 " + train.id() + " 的开门方向：" + doorOpeningSide);
            state.doorOpeningSide = doorOpeningSide;
        }

        let leftPartUseCjk = java.lang.Boolean.parseBoolean(state.leftPartUseCjkTracker.stateNow());
        let rightPartFullRouteMapUseCjk = state.rightPartFullRouteMapUseCjkTracker == null ? null : java.lang.Boolean.parseBoolean(state.rightPartFullRouteMapUseCjkTracker.stateNow());
        let rightPartScreenType = state.rightPartScreenTypeTracker == null ? null : state.rightPartScreenTypeTracker.stateNow();

        let g = state.dh.graphicsFor("lcd_door_left");
        drawScreen(slotCfg.slots[0].texArea[2], slotCfg.slots[0].texArea[3], g, state.routeInfo, state.doorOpenInfo, state.trainStatus == STATUS_RETURNING_TO_DEPOT ? 1 : train.getThisRoutePlatformsNextIndex(), state.trainStatus, leftPartUseCjk, rightPartFullRouteMapUseCjk, rightPartScreenType, train.isReversed(), train.manualAllowed(), train.isCurrentlyManual(), train, state.doorOpeningSide, state);

        g = state.dh.graphicsFor("lcd_door_right");
        drawScreen(slotCfg.slots[1].texArea[2], slotCfg.slots[1].texArea[3], g, state.routeInfo, state.doorOpenInfo, state.trainStatus == STATUS_RETURNING_TO_DEPOT ? 1 : train.getThisRoutePlatformsNextIndex(), state.trainStatus, leftPartUseCjk, rightPartFullRouteMapUseCjk, rightPartScreenType, !train.isReversed(), train.manualAllowed(), train.isCurrentlyManual(), train, state.doorOpeningSide, state);

        state.dh.upload();
    }
}

function shouldRepaintLCD(state, train) {
    let trainStatus = getTrainStatus(train);
    
    // 初始化状态跟踪
    if (!state.lastDoorOpeningState) {
        state.lastDoorOpeningState = train.isDoorOpening();
    }
    if (!state.lastRailProgress) {
        state.lastRailProgress = train.getRailProgress(0);
    }
    
    // 只有当列车正在开门时才设置为 STATUS_ARRIVED
    // 或者列车刚刚关门但还没有开始移动时，保持 STATUS_ARRIVED
    if (trainStatus == STATUS_ARRIVED) {
        if (train.isDoorOpening()) {
            // 正在开门，保持 STATUS_ARRIVED
        } else if (state.lastDoorOpeningState) {
            // 刚刚关门，保持 STATUS_ARRIVED
        } else {
            // 检查列车是否开始移动
            let currentProgress = train.getRailProgress(0);
            if (Math.abs(currentProgress - state.lastRailProgress) > 0.01) {
                // 列车已经开始移动，切换到 STATUS_ON_ROUTE
                trainStatus = STATUS_ON_ROUTE;
            } else {
                // 列车还没有开始移动，保持 STATUS_ARRIVED
            }
        }
    }
    
    // 更新状态跟踪
    state.lastDoorOpeningState = train.isDoorOpening();
    state.lastRailProgress = train.getRailProgress(0);
    
    if (checkProperty(state, "trainStatus", trainStatus)) { // 如果 state 中存在 trainStatus 且符合当前状态
        if (!state.leftPartUseCjkTracker.stateNowFirst() && (state.rightPartScreenTypeTracker == null || !state.rightPartScreenTypeTracker.stateNowFirst()) && (state.rightPartFullRouteMapUseCjkTracker == null || !state.rightPartFullRouteMapUseCjkTracker.stateNowFirst())) { // 并且各个屏幕不需要更新
            if (!CONFIG.showDoorOpenInfo || !train.isDoorOpening()) { // 并且无需绘制无法开门提示
                return false; // 无需重绘 LCD
            }
        }
        return true;
    } else {
        print("列车 " + train.id() + " 状态更新为：" + trainStatus);
        state.trainStatus = trainStatus;
        return true;
    }
}