import { EntityComponentTypes, system } from "@minecraft/server";
import { sendDebugMessage } from "./JM_Utils";

function driverLookAngle(locomotive) {
    const ridingComponent = locomotive.getComponent(EntityComponentTypes.Rideable)
    const player = ridingComponent?.getRiders()[ridingComponent.controllingSeat]
    // calculate angle
    const forward = locomotive.getViewDirection()
    const playerDir = player.getViewDirection()
    const dot = forward.x * playerDir.x + forward.z * playerDir.z
    const cross = forward.x * playerDir.z - forward.z * playerDir.x
    const angle = Math.atan2(cross,dot)
    return angle * (180/Math.PI)
}

system.afterEvents.scriptEventReceive.subscribe(event => {
    if (event.id !== "lb_ta:controls") return
    const locomotive = event.sourceEntity
    if (locomotive.hasComponent(EntityComponentTypes.Rideable) && locomotive.getComponent(EntityComponentTypes.Rideable).getRiders().length === 0) {
        // this happens when the trains are inside eachother and a player tries to interact with a train but the train they hit
        // is not the train they are riding.  The script event comes from the train they hit, so we have no way of knowing which player caused the event.
        // we could make an educated guess...
        sendDebugMessage(`${locomotive.typeId} has no riders!`)
        return
    }
    const degrees = driverLookAngle(locomotive)
    const args = event.message.split(" ")
    switch (args[0]) {
        case "interact":
            // positive = looking right (slow down)
            if (degrees > 0) {
                let speed = locomotive.getProperty("lifeboat_ta:speed")
                if (speed === 0) break
                speed--
                locomotive.setProperty("lifeboat_ta:speed",speed)
            } else { // looking left (bell/whistle)
                // if subway, there is no bell
                if (degrees > -45) horn(locomotive)
                else bell(locomotive)
            }
            break
        case "punch":
            // positive = looking right (speed up)
            if (degrees > 0) {
                // this is handled this way because the script does not give us any way to get the 
                // valid range for the property, which is different for each train
                const speed = locomotive.getProperty("lifeboat_ta:speed")
                try {
                    locomotive.setProperty("lifeboat_ta:speed",speed + 1)
                } catch (error) {
                    locomotive.setProperty("lifeboat_ta:speed",0)
                }
            } else { // looking left (toggle lights)
                locomotive.setProperty("lifeboat_ta:light_on",!locomotive.getProperty("lifeboat_ta:light_on"))
            }
            break
        default:
            // ignore
            sendDebugMessage(`unknown input: ${args[0]}`)
    }
})

function bell(locomotive) {
    const locomotiveShortName = locomotive.typeId.split(":")[1]
    let sound = bellsAndWhistles[locomotiveShortName].bell
    if (sound) {
        locomotive.dimension.playSound(sound, locomotive.location)
        locomotive.runCommand("playanimation @s animation.train_bell")
    } else {
        // locomotive does not have a bell; play horn sound instead
        horn(locomotive)
    }
}

function horn(locomotive) {
    const locomotiveShortName = locomotive.typeId.split(":")[1]
    let options = bellsAndWhistles[locomotiveShortName].horn
    let sound
    if (options.length === 1 && typeof options[0] === "string") sound = options[0]
    else {
        // multiple sounds available (steam sounds with lengths for particles)
        const chosen = options[Math.floor(Math.random() * options.length)]
        sound = chosen.sound
        locomotive.setProperty("lifeboat_ta:whistle_length",chosen.duration)
    }
    if (sound) {
        locomotive.dimension.playSound(sound, locomotive.location)
        locomotive.runCommand("playanimation @s animation.train_whistle")
    } else {
        // locomotive does not have a horn???!
        sendDebugMessage(`this should never happen...  ${locomotive.typeId} does not have a horn sound!`)
    }
}

const bellsAndWhistles = {
    "train_aem_7": {
        "bell": "ta_aem_bell",
        "horn": ["ta_aem_horn"]
    },
    "train_e2_steam": {
        "bell": "ta_e2_bell",
        "horn": [
            {
                sound: "ta_e2_horn_1",
                duration: 1.15
            },
            {
                sound: "ta_e2_horn_2",
                duration: 0.4
            },
            {
                sound: "ta_e2_horn_3",
                duration: 0.7
            }
        ]
    },
    "train_emdgp": {
        "bell": "ta_bell",
        "horn": ["ta_aem_horn"]
    },
    "train_metro": {
        "bell": "ta_bell",
        "horn": ["ta_metro_horn"]
    },
    "train_quarry": {
        "horn": [
            {
                sound: "ta_quarry_horn_1",
                duration: 1.4
            },
            {
                sound: "ta_quarry_horn_2",
                duration: 1.5
            },
            {
                sound: "ta_quarry_horn_3",
                duration: 0.9
            }
        ]
    },
    "train_subway": {
        "horn": ["ta_subway_horn"]
    },
    "train_t": {
        "bell": "ta_bell",
        "horn": [
            {
                sound: "ta_steam_whistle",
                duration: 3.5
            }
        ]
    },
    "train_upgtel": {
        "bell": "ta_bell",
        "horn": ["ta_horn"]
    }
}