import { world, system } from "@minecraft/server";
import { Director } from "./vector3.js";
import {attackPlayerMeikyu, attackFrameDated} from "./attackMethods.js";
import { EnemyClashPower } from "./utils.js";
import { launchPlayer } from "./movements.js";

export function ultimatum(player, ability, weaponType, timer, camerPresets, range, damage, block_damage, cooldown, atkspd, dist, targetNum, targetType, effect, launch_power, knockType, knockCheck, particle, combo_length, stunDamage, NAT, Unbreakable, damageType, item, hitNumber) {
    player.runCommand('execute as @s run inputpermission set @s movement disabled')
    for(let came = 0; came < camerPresets.length; came++){
        let camer = camerPresets[came]
        let Timex = (Math.floor(timer * camer.times))
        camer.times > 1 ? Timex = camer.times : Timex = Timex
        let Position = Director(player.getViewDirection(), player.location ,{x: camer.posX, y: camer.posY, z: camer.posZ})
        system.runTimeout(()=>{
            switch(camer.timeStamp) {
                case "restore_movement" :{
                    player.runCommand('execute as @s run inputpermission set @s movement enabled')
                    player.runCommand(`execute as @s run camera @s clear`)
                    player.runCommand(`execute as @s run tag @s remove attack`)
                    player.runCommand(`execute as @s run tag @s remove Immune`)
                    player.setDynamicProperty("combo", 1)
                    player.setDynamicProperty("attacking", 0)
                    world.scoreboard.getObjective("combatCooldown").setScore(player, 20)
                    world.scoreboard.getObjective("combatCheck").setScore(player, 0)
                    player.runCommand(`execute as @s run camera @s fade time 0.2 0.1 0.2 `)
                } break;
                case "add_status" :{
                    let statuser = JSON.parse(player.getDynamicProperty("resetingStatus"))
                    statuser[camer.boost] = statuser[camer.boost] + camer.changes
                    player.setDynamicProperty("resetingStatus", JSON.stringify(statuser))
                    player.setProperty("aura:color", 1)
                } break;
                case "attack_start" :{
                    player.runCommand(`execute as @s run tag @s add attack`)
                    attackPlayerMeikyu(player, range, damage, block_damage, cooldown, atkspd, dist, targetNum, targetType, effect, launch_power, knockType, knockCheck, particle, combo_length, stunDamage, NAT, Unbreakable, damageType, item, hitNumber, true)
                    player.camera.setCamera(camer.cameraType, {
                        easeOptions: {
                            easeTime: camer.easing,
                            easeType: camer.transitionType
                        },
                        //facingEntity: player,
                        facingLocation: camer.facing,
                        location: Position
                    })
                    
                } break;
                case "shake" :{
                    player.runCommand(`execute as @s run camerashake add @s ${camer.intensity} ${camer.time} ${camer.shakeType}`)
                } break;
                case "fade" :{
                    player.runCommand(`execute as @s run camera @s fade time 0.2 0.1 0.2 `)
                } break;
                case "add_impact_frame" :{
                    player.dimension.spawnEntity("minced:impact_frame", Position)
                    let dx = player.location.x - hell.location.x;
                    let dy = player.location.y - hell.location.y;
                    let dz = player.location.z - hell.location.z;

                    let yaw = Math.atan2(dz, dx) * (180 / Math.PI)-90;
                    let distanceXZ = Math.sqrt(dx * dx + dz * dz);
                    let pitch = -Math.atan2(dy, distanceXZ) * (180 / Math.PI);
                    
                    let hellish = player.dimension.spawnEntity(camer.spawn, player.location)
                    hellish.setRotation({x:pitch, y:yaw})
                } break;
                default: {
                    player.camera.setCamera(camer.cameraType, {
                        easeOptions: {
                            easeTime: camer.easing,
                            easeType: camer.transitionType
                        },
                        facingEntity: player,
                        //facingLocation: camer.facing,
                        location: Position
                    })
                } break;
            }
        },Timex)
        system.runTimeout(()=>{
            player.runCommand(`execute as @p run camera @s clear`)
        },(Math.floor(timer + 5)))
    }
}


async function attackMultiFrame(player, camerPresets, damage, block_damage, cooldown, effect, stunDamage, item) {
    let attackFrameCount = 0
    let finalTime
    let oldFrameatkspd = 0
    for await (let came of camerPresets.frames){
        let camer = came
        let Timex = camer.attack_timeFrame - oldFrameatkspd
        switch(camer.timeStamp) {
            case "restore_movement" :{
                system.runTimeout(async ()=>{
                    player.removeTag("attack")
                },Timex)
                attackFrameCount = attackFrameCount + 1
            } break;
            case "add_particle_effect": {
                let particleLoc = Director(player.getViewDirection(), player.location, camer.distanceOffset)
                player.dimension.spawnParticle(camer.particle,particleLoc);
            } break;
            case "player_knockback": {
                launchPlayer(player, camer.Pknockback[0], camer.Pknockback[1])
            } break;
            case "add_frame" :{
                if(camer.Unbreakable == true) {
                    player.addTag("Unbreakable")
                }
                switch(camer.FrameMode) {
                    case "math_frame" :{
                        player.runCommand(`execute as @s run tag @s add attack`)
                    } break;
                    default: {
                        let goer = await attackFrameDated(player, Timex, camer.range, damage, block_damage, camer.distanceOffset, camer.targetNum, effect, camer.knockback, camer.stun_type, camer.knockCheck, camer.type, stunDamage, camer.Unbreakable, "normal", item)
                        oldFrameatkspd = camer.attack_timeFrame
                        attackFrameCount = attackFrameCount + 1
                        finalTime = goer
                    } break;
                }
            } break;
            case "checkParry" :{
                EnemyClashPower(player,"start",camerPresets.attackTime)
                attackFrameCount = attackFrameCount + 1
            } break;
            default: {
                attackFrameCount = attackFrameCount + 1
            } break;
        }
        if(attackFrameCount >= camerPresets.frames.length||finalTime == "clashed"||finalTime == "countered") {
            return new Promise((resolve) => {
                if(attackFrameCount >= camerPresets.attackFrameNumber||finalTime == "clashed"||finalTime == "countered") {
                    resolve(finalTime)
                }
            })
        }
    }
}

export async function attackFramerMeikyu(player, camerPresets, damage, block_damage, cooldown, effect, combo_length, stunDamage, NAT, item, inputDisabled) {
    player.addEffect("weakness", camerPresets.attackTime + cooldown, { amplifier: 100, showParticles: false })
    if(inputDisabled == true) {
        try{
            player.inputPermissions.movementEnabled = false
        } catch (e) {
            player.addEffect("slowness", camerPresets.attackTime , { amplifier: 100, showParticles: false })
        }
    }
    let comboGet = player.getDynamicProperty("combo")
    world.scoreboard.getObjective("clash").addScore(player, 0)
    world.scoreboard.getObjective("stunned").setScore(player, 0)
    const waiter = await attackMultiFrame(player, camerPresets, damage, block_damage, cooldown, effect, stunDamage, item)
    let statusUpdate = JSON.parse(player.getDynamicProperty("resetingStatus"))
    let comboed = false
    let che4ck = world.scoreboard.getObjective("stunbreak").getScore(player)
    player.setProperty("mode:combat", 1)
    player.removeTag("Unbreakable")
    player.removeTag("attack")
    world.scoreboard.getObjective("clash").setScore(player, 0)
    if(comboGet >= combo_length) {
        player.setDynamicProperty("combo", 1)
        comboed = true
        statusUpdate["powerBar"] = statusUpdate.powerBar + Math.floor((damage/3))
        statusUpdate.powerBar >= 100 ? statusUpdate["powerBarTrigger"] = 1 : statusUpdate["powerBarTrigger"] = 0
        player.setDynamicProperty("resetingStatus", JSON.stringify(statusUpdate))
        system.runTimeout(()=>{
            if(comboed == true || player.getDynamicProperty("attacking") == 1 && waiter != "attack_finished" && waiter == "nothing") {
                player.setDynamicProperty("combo", 1)
                player.setDynamicProperty("attacking", 0)
                if(che4ck != 1) {
                    try{
                        player.inputPermissions.movementEnabled = true
                    } catch (e) {
                        
                    }
                } 
            }   
        },(cooldown + NAT))
        world.scoreboard.getObjective("combatCooldown").setScore(player, (cooldown + NAT))
        world.scoreboard.getObjective("combatCheck").setScore(player, 0)
    } else if(comboGet <= combo_length) {
        let newCombo = comboGet + 1
        player.setDynamicProperty("combo", newCombo)
        statusUpdate["powerBar"] = statusUpdate.powerBar + Math.floor((damage/3))
        statusUpdate.powerBar >= 100 ? statusUpdate["powerBarTrigger"] = 1 : statusUpdate["powerBarTrigger"] = 0
        player.setDynamicProperty("resetingStatus", JSON.stringify(statusUpdate))
        system.runTimeout(()=>{
            player.setDynamicProperty("attacking", 0)
            if(che4ck != 1) {
                try{
                    player.inputPermissions.movementEnabled = true
                } catch (e) {
                        
                }
            }
        },NAT)
        world.scoreboard.getObjective("combatCooldown").setScore(player, (cooldown))
        world.scoreboard.getObjective("combatCheck").setScore(player, 0)
    }
}

