const RU = Resources;
const MM = ModelManager;
const MCU = MinecraftClient;
include(Resources.id("aphrodite:library/code/util/error_supplier.js"));
include(Resources.id("aphrodite:library/code/gui/orderly_responder.js"));

// Load models
const MODELS = MM.loadPartedRawModel(RU.manager(), RU.id("mtrsteamloco:eyecandies/signals/theatre.obj"), null);

const BASE = ModelManager.uploadVertArrays(MODELS.get("base"));

const modelRefs = {
  a: MM.uploadVertArrays(MODELS.get("a")),
  b: MM.uploadVertArrays(MODELS.get("b")),
  c: MM.uploadVertArrays(MODELS.get("c")),
  d: MM.uploadVertArrays(MODELS.get("d")),
  e: MM.uploadVertArrays(MODELS.get("e")),
  f: MM.uploadVertArrays(MODELS.get("f")),
  g: MM.uploadVertArrays(MODELS.get("g")),
  h: MM.uploadVertArrays(MODELS.get("h")),
  i: MM.uploadVertArrays(MODELS.get("i")),
  j: MM.uploadVertArrays(MODELS.get("j")),
  k: MM.uploadVertArrays(MODELS.get("k")),
  l: MM.uploadVertArrays(MODELS.get("l")),
  m: MM.uploadVertArrays(MODELS.get("m")),
  n: MM.uploadVertArrays(MODELS.get("n")),
  o: MM.uploadVertArrays(MODELS.get("o")),
  p: MM.uploadVertArrays(MODELS.get("p")),
  q: MM.uploadVertArrays(MODELS.get("q")),
  r: MM.uploadVertArrays(MODELS.get("r")),
  s: MM.uploadVertArrays(MODELS.get("s")),
  t: MM.uploadVertArrays(MODELS.get("t")),
  u: MM.uploadVertArrays(MODELS.get("u")),
  v: MM.uploadVertArrays(MODELS.get("v")),
  w: MM.uploadVertArrays(MODELS.get("w")),
  x: MM.uploadVertArrays(MODELS.get("x")),
  y: MM.uploadVertArrays(MODELS.get("y")),
  z: MM.uploadVertArrays(MODELS.get("z")),
};

// Handle numbers (num0-num19)
for (let i = 0; i <= 19; i++) {
  modelRefs[`num${i}`] = ModelManager.uploadVertArrays(MODELS.get(i.toString()));
}

// Handle alphabets (a-z)



const pos0 = MM.uploadVertArrays(MODELS.get("pos0"));
const pos1 = MM.uploadVertArrays(MODELS.get("pos1"));
const pos2 = MM.uploadVertArrays(MODELS.get("pos2"));
const pos3 = MM.uploadVertArrays(MODELS.get("pos3"));
const pos4 = MM.uploadVertArrays(MODELS.get("pos4"));
const pos5 = MM.uploadVertArrays(MODELS.get("pos5"));
const pos6 = MM.uploadVertArrays(MODELS.get("pos6"));

const slash = MM.uploadVertArrays(MODELS.get("slash"));
const invslash = MM.uploadVertArrays(MODELS.get("invslash"));

const clear = MM.uploadVertArrays(MODELS.get("repeater_clear"));
const proceed = MM.uploadVertArrays(MODELS.get("repeater_proceed"));
const danger = MM.uploadVertArrays(MODELS.get("repeater_danger"));


//custom input setup
const nodePosKey = "custom";
const modeKey = "mode";
const repeaterAspectKey = "2";
const repeaterAspectType = "0";
const aspectClear = "pos0";
const aspectOccupied = "";


const nodePosINPUT = new ConfigResponder.TextField(
    nodePosKey,
    ComponentUtil.literal("Node Pos (x,y,z)"),
    ""
).setTooltipSupplier(str => Optional.of(asJavaArray([
    ComponentUtil.literal("Leave empty to auto-detect."),
    ComponentUtil.literal("Format: x,y,z)")
], Component)))
    .setErrorSupplier(str => {
        if (!str) return Optional.empty();
        const parts = str.split(",");
        if (parts.length !== 3 || parts.some(p => isNaN(parseFloat(p)))) {
            return Optional.of(ComponentUtil.literal("Invalid format. Use x,y,z."));
        }
        return Optional.empty();
    })


const MODE_RESPONDER = new ConfigResponder.TextField(
    modeKey,
    ComponentUtil.translatable("name.raf.mode"),
    "0"
).setErrorSupplier(str => {
    if (!["0", "1"].includes(str)) {
        return Optional.of(ComponentUtil.translatable("error.aph.invalid_value"));
    }
    return Optional.empty();
}).setTooltipSupplier(str => Optional.of(asJavaArray([ComponentUtil.translatable("0-Route indicator 1-Repeater")], Component)));


const REPEATER_RESPONDER = new ConfigResponder.TextField(
    repeaterAspectKey,
    ComponentUtil.translatable("select.repeater.type"),
    "2"
).setErrorSupplier(str => {
    if (!["2", "3", "4"].includes(str)) {
        return Optional.of(ComponentUtil.translatable("error.aph.invalid_value"));
    }
    return Optional.empty();
}).setTooltipSupplier(str => Optional.of(asJavaArray([ComponentUtil.translatable("2,3,4")], Component)));


const ASPECT_RESPONDER = new ConfigResponder.TextField(
    repeaterAspectType,
    ComponentUtil.translatable("select.repeater.aspect"),
    "0"
).setErrorSupplier(str => {
    if (!["0", "1", "2","3"].includes(str)) {
        return Optional.of(ComponentUtil.translatable("error.aph.invalid_value"));
    }
    return Optional.empty();
}).setTooltipSupplier(str => Optional.of(asJavaArray([ComponentUtil.translatable("0-auto 1-danger 2-proceed 3-clear")], Component)));


const CLEAR_ASPECT = new ConfigResponder.TextField(
    aspectClear,
    ComponentUtil.translatable("select.clear"),
    ""
).setErrorSupplier(str => {
    return Optional.empty();
}).setTooltipSupplier(str => Optional.of(asJavaArray([ComponentUtil.translatable("lowercase")], Component)));


const OCCUPIED_ASPECT = new ConfigResponder.TextField(
    aspectOccupied,
    ComponentUtil.translatable("select.occupied"),
    ""
).setErrorSupplier(str => {
    
    return Optional.empty();
}).setTooltipSupplier(str => Optional.of(asJavaArray([ComponentUtil.translatable("lowercase")], Component)));


const RESS = orderlyResponder("Route Indicator", "Made by Andy_Wongg", [MODE_RESPONDER, ASPECT_RESPONDER, nodePosINPUT, CLEAR_ASPECT, OCCUPIED_ASPECT,REPEATER_RESPONDER]);


//setup eyecandy
function create(ctx, state, entity) {
    entity.registerCustomConfig(RESS);
    entity.sendUpdateC2S();
}

function render(ctx, state, entity) {
    let mat = new Matrices();
    mat.translate(0, 0.00625, 0);
    ctx.drawModel(BASE, mat);

    let mode = entity.getCustomConfig(modeKey) + "";
    let clearaspect = entity.getCustomConfig(aspectClear) + "";
    let occupiedaspect = entity.getCustomConfig(aspectOccupied) + "";
    let aspectkey = entity.getCustomConfig(repeaterAspectKey) + "";
    let aspect = entity.getCustomConfig(repeaterAspectType) + "";

    let oa = -1;
    try {
        let pos = entity.getWorldPosVector3f();
        let facing = entity.getBlockYRot() + entity.rotateY / Math.PI * 180 + 90;
        let nodePosStr = entity.getCustomConfig(nodePosKey);
        let nodePos;

        if (nodePosStr && nodePosStr.trim() !== "") {
            const parts = nodePosStr.split(",").map(Number);
            if (parts.length === 3 && parts.every(n => !isNaN(n))) {
                nodePos = new Vector3f(parts[0], parts[1], parts[2]);
            }
        }

        if (!nodePos) {
            nodePos = MCU.getNodeAt(pos, facing);
        }
        oa = MCU.getOccupiedAspect(nodePos, facing, 4); // 4 possible aspects
    } catch (e) {}

    // Decide which model to draw
    let modelToDraw = null;

    if (mode == 0) {//ri
        if (oa == 1) {
            if ( occupiedaspect === "pos0") modelToDraw = pos0;
            else if ( occupiedaspect === "pos1") modelToDraw = pos1;
            else if ( occupiedaspect === "pos2") modelToDraw = pos2;
            else if ( occupiedaspect === "pos3") modelToDraw = pos3;
            else if ( occupiedaspect === "pos4") modelToDraw = pos4;
            else if ( occupiedaspect === "pos5") modelToDraw = pos5;
            else if ( occupiedaspect === "pos6") modelToDraw = pos6;
            else if ( occupiedaspect === "slash"||occupiedaspect === "/") modelToDraw = slash;
            else if ( occupiedaspect === "invslash"||occupiedaspect === "\\") modelToDraw = invslash;
            else if (/^\d+$/.test(occupiedaspect)) {
                modelToDraw = modelRefs[`num${occupiedaspect}`];
            }else {
                modelToDraw = modelRefs[`${occupiedaspect}`];
            }
        }else if (oa != 1) {
            if ( clearaspect === "pos0") modelToDraw = pos0;
            else if ( clearaspect === "pos1") modelToDraw = pos1;
            else if ( clearaspect === "pos2") modelToDraw = pos2;
            else if ( clearaspect === "pos3") modelToDraw = pos3;
            else if ( clearaspect === "pos4") modelToDraw = pos4;
            else if ( clearaspect === "pos5") modelToDraw = pos5;
            else if ( clearaspect === "pos6") modelToDraw = pos6;
            else if ( clearaspect === "slash"||clearaspect === "/") modelToDraw = slash;
            else if ( clearaspect === "invslash"||clearaspect === "\\") modelToDraw = invslash;
            else if (/^\d+$/.test(clearaspect)) {
                modelToDraw = modelRefs[`num${clearaspect}`];
            }else {
                modelToDraw = modelRefs[clearaspect];
            }
        }}
    else if (mode == 1){//repeater
        if (aspect == 0){
            if (aspectkey == 2){
                if(oa===-1){}
                else if(oa==1){
                    modelToDraw = danger
                }else{
                    modelToDraw = proceed
                }
            }else if (aspectkey == 3){
                if(oa==-1){}
                else if(oa==1){
                    modelToDraw = danger
                }else if(oa==2){
                    modelToDraw = proceed
                }else{modelToDraw = clear}
            }else if (aspectkey == 4){
                if(oa==-1){}
                else if(oa==1){
                    modelToDraw = danger
                }else if(oa==2||oa==3){
                    modelToDraw = proceed
                }else{modelToDraw = clear}
            }
        }else if (aspect == 1) modelToDraw = danger;
        else if (aspect == 2) modelToDraw = proceed;
        else if (aspect == 3) modelToDraw = clear;

    }

    if (modelToDraw != null) {
        ctx.drawModel(modelToDraw, mat);
    }
}
