include("mtrsteamloco:scripts/train_mtr_util.js");
include("mtrsteamloco:scripts/train_js_util.js");
include("mtrsteamloco:scripts/train_text_util.js");
include(Resources.id("mtrsteamloco:scripts/display_helper.js"));
importPackage(java.lang);
importPackage(java.util.concurrent);
include("draw.js");
include("disp.js");
importPackage(java.awt);
importPackage(java.awt.geom);

// var trainConfig = JSON.parse(Resources.readString(Resources.id("mtr:asm1a/config.json")));
var slotCfg = trainConfig.slots;
var dispSlotCfg = trainConfig.dispSlots;

var dhBase = new DisplayHelper(slotCfg);
var dhBaseDisp = new DisplayHelper(dispSlotCfg);

const forwardLCDOffset = -0.5;
const backwardLCDOffset = 0.5;
const firstLCDOffset = -1;
const lastLCDOffset = 1;

function create(ctx, state, train) {
    state.drawRoute = getDrawableRoute(state, train, ctx);
    ctx.setDebugInfo("drawRoute", JSON.stringify(state.drawRoute));

    // ctx.setDebugInfo("thisRoute", state.drawRoute.finalThisRouteStations);

    state.dh = dhBase.create();
    state.dhDisp = dhBaseDisp.create();
    state.pisRateLimit = new RateLimit(0.05);
    state.pisRateLimitDisp = new RateLimit(0.001);
    state.dispText = "";
}

function render(ctx, state, train) {
    if (state.cacheTrainStatus != getTrainStatus(train)) {
        state.drawRoute = getDrawableRoute(state, train, ctx);
        ctx.setDebugInfo("drawRoute", JSON.stringify(state.drawRoute));
        state.cacheTrainStatus = getTrainStatus(train);
    }

    if (state.pisRateLimitDisp.shouldUpdate()) {
        let gD = state.dhDisp.graphics();
        try {
            drawDisp(gD, state.drawRoute, dispSlotCfg.slots[0].texArea, state, train, trainConfig);
        } catch (e) {}
        state.dhDisp.texture.upload();
    }
    if (state.pisRateLimit.shouldUpdate()) {
        let doorInfo = {};
        let g = state.dh.graphics();

        if (!state.doorVal) state.doorVal = 0;
        if (train.doorValue() > state.cacheDoorVal || train.doorValue() == 1) {
            state.doorVal += Timing.delta() * 6;
            if (state.doorVal > 1) state.doorVal = 1;
        } else {
            state.doorVal -= Timing.delta() * 6;
            if (state.doorVal < 0) state.doorVal = 0;
        }
        state.cacheDoorVal = train.doorValue();

        doorInfo = { isLeft: true, cart: 1 };
        try {
            drawLCD(g, state.drawRoute, slotCfg.slots[0].texArea, state, train, trainConfig, doorInfo);
        } catch (e) {
            setErrorInfo(e);
        }
        doorInfo = { isLeft: false, cart: 1 };
        try {
            drawLCD(g, state.drawRoute, slotCfg.slots[1].texArea, state, train, trainConfig, doorInfo);
        } catch (e) {}
        state.dh.texture.upload();
    }
    let isForwarding = train.isReversed() == false;
    for (let i = 0; i < train.trainCars(); i++) {
        let mat = new Matrices();

        mat.translate(0, 0, isForwarding ? forwardLCDOffset : backwardLCDOffset);
        mat.pushPose();

        if (i == 0) mat.translate(0, 0, firstLCDOffset);
        if (i == train.trainCars() - 1) mat.translate(0, 0, lastLCDOffset);

        ctx.drawCarModel(state.dh.model, i, mat);

        mat.popPose();
        mat.pushPose();
        mat.translate(0, 0, -9.611);

        if (i != train.trainCars() - 1) ctx.drawCarModel(state.dhDisp.model, i, mat);

        mat.popPose();
        mat.pushPose();
        mat.rotateY(Math.PI);
        mat.translate(0, 0, -9.611);

        if (i != 0) ctx.drawCarModel(state.dhDisp.model, i, mat);

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