import { world, system, EntityDamageCause } from '@minecraft/server'
import { ModalFormData } from '@minecraft/server-ui'

world.beforeEvents.chatSend.subscribe((event) => {
    player.runCommandAsync(`execute as @a unless score @s speed = @s speed run scoreboard players set @s speed 2`)
    let player = event.sender
    if (event.message.valueOf() === '!freecam settings') {
        if (player.hasTag('in_freecam')) {
            event.cancel = true;
            player.sendMessage('§uYou are in Free Camera Mode. Speed cannot be adjusted while in Free Camrea Mode.')
        }
        if (!player.hasTag('in_freecam')) {
            event.cancel = true;
            player.runCommandAsync('scriptevent rl:message open_form')
        }
    }
})

system.afterEvents.scriptEventReceive.subscribe((event) => {
    let player = event.sourceEntity
    let currentSpeed = world.scoreboard.getObjective(`speed`).getScore(player)
    let form = new ModalFormData();
    form.title("Free Camera Settings");
    form.slider("Camera Speed", 1, 10, 1, currentSpeed);
    const health = player.getComponent("health");
    const { currentValue: current } = health;
    if (current >= 2) {
        // We need to switch player to gamemode where we can apply damage to them
        player.runCommand("execute if entity @s[m=c] run tag @s add gm_change");
        player.runCommand("execute if entity @s[tag=gm_change] run gamemode s");

        player.applyDamage(1, {
            cause: EntityDamageCause.entityAttack
        });
        health.setCurrentValue(current);
        player.runCommand("stopsound @s game.player.hurt");

        // Return player back to creative mode
        player.runCommand("execute if entity @s[tag=gm_change] run gamemode c");
        player.runCommand("execute if entity @s[m=c,tag=gm_change] run tag @s remove gm_change");
    }
    if (current <= 1) {

        // We need to switch player to gamemode where we can apply damage to them
        player.runCommand("execute if entity @s[m=c] run tag @s add gm_change");
        player.runCommand("execute if entity @s[tag=gm_change] run gamemode s");

        player.addEffect('instant_health', 1, { amplifier: 1 })
        system.runTimeout(() => {
            player.applyDamage(1, {
                cause: EntityDamageCause.entityAttack
            });
            health.setCurrentValue(current);
            player.runCommand("stopsound @s game.player.hurt");

            // Return player back to creative mode
            player.runCommand("execute if entity @s[tag=gm_change] run gamemode c");
            player.runCommand("execute if entity @s[m=c,tag=gm_change] run tag @s remove gm_change");
        }, 1);
    }
    system.runTimeout(() => {
        form.show(player).then(r => {
            if (r.canceled) return;
            let [slider] = r.formValues;
            player.runCommandAsync(`scoreboard players set @s speed ${slider}`)
        }).catch((e) => {
            console.error(e, e.stack);
        })
    }, 20);
})

world.beforeEvents.chatSend.subscribe((eventData) => {
    let player = eventData.sender
    let name = player.nameTag
    player.runCommandAsync(`scoreboard objectives add speed dummy Speed`)
    let speed = world.scoreboard.getObjective(`speed`).getScore(player)
    system.runInterval(() => {
        if (player.isJumping === true) {
            player.runCommandAsync(`execute unless entity @a[name=${name},tag=freecam_locked] as @e[type=rl:freecam_dummy,tag=${name}] at @s rotated as ${name} run tp @s ^^^${speed / 10}`)
        }
        if (player.isSneaking === true) {
            player.runCommandAsync(`execute unless entity @a[name=${name},tag=freecam_locked] as @e[type=rl:freecam_dummy,tag=${name}] at @s rotated as ${name} run tp @s ^^^-${speed / 10}`)
        }
        player.runCommandAsync(`execute as @a[tag=in_freecam,name=${name}] at @e[type=rl:freecam_dummy,tag=${name}] run camera @s set minecraft:free ease 0.1 linear pos ~ ~ ~`)
        player.runCommandAsync(`execute as @a[tag=in_freecam,name=${name},tag=!freecam_locked] run camera @s set minecraft:free ease 0.1 linear facing ^ ^ ^99999`)
        player.runCommandAsync(`execute as @a[tag=!in_freecam] run camera @s clear`)
    }, 1);
    if (eventData.message.valueOf() === '!freecam start') {
        if (player.hasTag('in_freecam')) {
            player.sendMessage('§uYou are already in Free Camera Mode')
            eventData.cancel = true;
        }
        if (!player.hasTag('in_freecam')) {
            eventData.cancel = true;
            player.runCommandAsync(`kill @e[type=rl:freecam_dummy,tag=${name}]`)
            player.runCommandAsync("stopsound @s game.player.die");
            player.runCommandAsync(`tag ${name} remove freecam_locked`);
            player.runCommandAsync(`tag ${name} add in_freecam`);
            player.runCommandAsync('summon rl:freecam_dummy ~ ~2 ~')
            player.runCommandAsync(`tellraw ${name}{"rawtext":[{"text":"§rToggled Free Camera §qOn"}]}`)
            player.runCommandAsync(`tag @e[type=rl:freecam_dummy,c=1] add ${name}`)
        }
    }
    if (eventData.message.valueOf() === '!freecam end') {
        if (!player.hasTag('in_freecam')) {
            player.sendMessage('§uYou are not in Free Camera Mode')
            eventData.cancel = true;
        }
        if (player.hasTag('in_freecam')) {
            eventData.cancel = true;
            player.runCommandAsync(`tag ${name} remove in_freecam`);
            player.runCommandAsync(`tag ${name} remove freecam_locked`);
            player.runCommandAsync(`tellraw ${name}{"rawtext":[{"text":"§rToggled Free Camera §mOff"}]}`)
            player.runCommandAsync(`kill @e[type=rl:freecam_dummy,tag=${name}]`)
            player.runCommandAsync("stopsound @s game.player.die");
        }
    }
    if (eventData.message.valueOf() === '!freecam unlock') {
        if (!player.hasTag('in_freecam')) {
            player.sendMessage('§uYou are not in Free Camera Mode')
            eventData.cancel = true;
        }
        if (player.hasTag('in_freecam')) {
            if (!player.hasTag('freecam_locked')) {
                player.sendMessage('§uCamera Position is already Unlocked')
                eventData.cancel = true;
            }
            if (player.hasTag('freecam_locked')) {
                eventData.cancel = true;
                player.runCommandAsync(`tag ${name} remove freecam_locked`);
                player.runCommandAsync(`tellraw ${name}{"rawtext":[{"text":"§jCamera Position Unlocked"}]}`)
            }
        }
    }
    if (eventData.message.valueOf() === '!freecam lock') {
        if (!player.hasTag('in_freecam')) {
            player.sendMessage('§uYou are not in Free Camera Mode')
            eventData.cancel = true;
        }
        if (player.hasTag('in_freecam')) {
            if (player.hasTag('freecam_locked')) {
                player.sendMessage('§uCamera Position is already Locked')
                eventData.cancel = true;
            }
            if (!player.hasTag('freecam_locked')) {
                eventData.cancel = true;
                player.runCommandAsync(`tag ${name} add freecam_locked`);
                player.runCommandAsync(`tellraw ${name}{"rawtext":[{"text":"§jCamera Position Locked"}]}`)
                player.runCommandAsync(`tag @e[type=rl:freecam_dummy,c=1] add ${name}`)
            }
        }
    }
});