import { world, system, StructureAnimationMode, EntityComponentTypes, ItemStack, EquipmentSlot, Player, EasingType, StructureRotation} from '@minecraft/server'
import { scanerMobs,WEAPONS,WEAPONS_DATA,spawnEntitiesInLine, getItem, spawnRandomMinionsPlayer } from '../bosses/communs';
import { structure_confirm } from '../menus/structure';

const ITEM_STRUCUTRE = {
    'ns_ab:raijin_structure': {
        structure: 'raijin',
        locationSpawn: {
            x: 1,
            y: 0,
            z: -20
        },
        positionCamera: {
            x: 0,
            y: 32,
            z: -60,
        }
    },
    'ns_ab:ganimedes_structure': {
        structure: 'ganimedes',
        locationSpawn: {
            x: 0,
            y: 0,
            z: 30
        },
        positionCamera: {
            x: 0,
            y: 32,
            z: 40,
        }
    },
    'ns_ab:hanniya_structure': {
        structure: 'hannya',
        locationSpawn: {
            x: 0,
            y: 0,
            z: 30
        },
        positionCamera: {
            x: 0,
            y: 32,
            z: 40,
        }
    },
    'ns_ab:ice_wolf_structure': {
        structure: 'freezingwolf',
        locationSpawn: {
            x: 0,
            y: 0,
            z: -30
        },
        positionCamera: {
            x: 0,
            y: 32,
            z: -60,
        }
    },
    'ns_ab:fire_dragon_structure': {
        structure: 'dragonfire',
        locationSpawn: {
            x: 0,
            y: 0,
            z: -26
        },
        positionCamera: {
            x: 0,
            y: 32,
            z: -50,
        }
    },
    'ns_ab:necromancer_king_structure': {
        structure: 'necromancer_king',
        locationSpawn: {
            x: 20,
            y: 0,
            z: 0
        },
        positionCamera: {
            x: 54,
            y: 32,
            z: 0,
        }
    },
    'ns_ab:spider_mother_structure': {
        structure: 'spider_mother',
        locationSpawn: {
            x: 30,
            y: 0,
            z: 0
        },
        positionCamera: {
            x: 56,
            y: 32,
            z: 0,
        }
    },
    'ns_ab:tengu_structure': {
        structure: 'tengu',
        locationSpawn: {
            x: 0,
            y: 0,
            z: 30
        },
        positionCamera: {
            x: 0,
            y: 32,
            z: 40,
        }
    },
    'ns_ab:zombie_swordman_structure': {
        structure: 'zombieboss',
        locationSpawn: {
            x: 0,
            y: 0,
            z: 30
        },
        positionCamera: {
            x: 0,
            y: 32,
            z: 40,
        }
    },
}

const DATA_STRUCTURE = {}

world.afterEvents.itemUse.subscribe((event) => {
    const { itemStack, source } = event;
    if (WEAPONS[itemStack.typeId]) {
        const { damage, on_fire, item_cooldown, timer, type_attack } = WEAPONS[itemStack.typeId]
        const { first_vision, third_vision } = type_attack;
        const cooldown = source.getItemCooldown(item_cooldown)
        if (!source.isSneaking && cooldown == 0) {
            camera(source)
            use_ability( 
                source,
                itemStack,
                timer,
                first_vision.animation,
                first_vision.vfx,
                cooldown,
                item_cooldown
            )
        }
        else if (source.isSneaking && cooldown == 0){
            switch (itemStack.typeId) {
                case 'ns_ab:red_katana': {
                    use_ability( 
                        source,
                        itemStack,
                        timer,
                        third_vision.animation,
                        third_vision.vfx,
                        cooldown,
                        item_cooldown
                    )
                    fire_impact(source)
                    source.playSound('tengu.fire_sword')
                    camera(source)
                    break
                }
                case 'ns_ab:water_dual_blades': {
                    use_ability( 
                        source,
                        itemStack,
                        timer,
                        third_vision.animation,
                        third_vision.vfx,
                        cooldown,
                        item_cooldown
                    )
                    source.playSound('hanniya.water_sword')
                    camera(source)
                    break
                }
                case 'ns_ab:double_daggers': {
                    use_ability( 
                        source,
                        itemStack,
                        timer,
                        third_vision.animation,
                        third_vision.vfx,
                        cooldown,
                        item_cooldown
                    )
                    source.addEffect('invisibility',20*20,{showParticles:false}),
                    source.playSound('ganimedes.vanish1')
                    camera(source)
                    break
                }
                case 'ns_ab:necromancer_sword': {
                    use_ability( 
                        source,
                        itemStack,
                        timer,
                        third_vision.animation,
                        third_vision.vfx,
                        cooldown,
                        item_cooldown
                    )
                    remove_tamed(source,["ns_ab:minion_zombie","ns_ab:skeleton_sword"])
                    spawnRandomMinionsPlayer(["ns_ab:spawn_tame_zombie","ns_ab:spawn_tame_skeleton"], source, source)
                    camera(source)
                    break
                }
                case 'ns_ab:lighting_stick':{
                    use_ability( 
                        source,
                        itemStack,
                        timer,
                        third_vision.animation,
                        third_vision.vfx,
                        cooldown,
                        item_cooldown
                    )
                    let view = source.getViewDirection()
                    source.applyKnockback(5*view.x,5*view.z,10,0)
                    camera(source)
                    break
                }
            }
        }
        
    }
    if (source.getItemCooldown('ice_crystal') == 0 && itemStack.typeId == 'ns_ab:ice_crystal') {
        source.addTag('owner')
        source.playSound('ice.icespikes')
        let viewEntities = source.getEntitiesFromViewDirection({
            maxDistance: 40,
        })
        if (viewEntities.length > 0) {
            viewEntities.forEach((target) => {
                let entity = target.entity
                if (entity.typeId != 'ns_ab:ice_spike') {
                    spawnEntitiesInLine("ns_ab:ice_spike", source.location, entity.location, source);
                    source.startItemCooldown('ice_crystal',6*20)
                }
            })
        } else {
            let block = source.getBlockFromViewDirection({
                maxDistance: 40,
                includeLiquidBlocks: false,
                includePassableBlocks: false
            });
            if (block != undefined){
                spawnEntitiesInLine("ns_ab:ice_spike", source.location, block.block.location, source)
                source.startItemCooldown('ice_crystal',6*20)
            }
        }
    }
    if (ITEM_STRUCUTRE[itemStack.typeId]) {
        const form = structure_confirm();
        form.show(source).then((response) => {
            if (response.cancelationReason || response.canceled) return;
            switch (response.selection) {
                case 0: {
                    const itemData = ITEM_STRUCUTRE[itemStack.typeId];
                    if (!ITEM_STRUCUTRE[source.nameTag]?.item_use ?? false) {
                        let structure = world.structureManager.get(`ns_ab:${itemData.structure}`);
                        if (!structure) {
                            console.error('Estrutura não encontrada:', itemData.structure);
                            return;
                        }
                        world.structureManager.place(structure, source.dimension, {
                            x: source.location.x - 31,
                            y: source.location.y,
                            z: source.location.z - 32,
                        }, {
                            includeEntities: true,
                            includeBlocks: true,
                            animationMode: StructureAnimationMode.Layers,
                            animationSeconds: 15
                        });
                        source.addEffect('slow_falling', 10 * 20);
                        source.tryTeleport({
                            x: source.location.x+ itemData.locationSpawn.x,
                            y: source.location.y + 24,
                            z: source.location.z + itemData.locationSpawn.z,
                        },
                        {
                            rotation: {
                                x: 0,
                                y: 0
                            },
                            facingLocation: {
                                x: 0,
                                y: 0,
                                z: 0
                            }
                        });
                        source.camera.setCamera('minecraft:free', {
                            location: {
                                x: source.location.x + itemData.positionCamera.x,
                                y: source.location.y + itemData.positionCamera.y,
                                z: source.location.z + itemData.positionCamera.z,
                            },
                            facingEntity: source,
                            easeOptions: {
                                easeTime: 7.5,
                                easeType: EasingType.InOutSine
                            }
                        });
    
                        source.runCommand(`setblock ${source.location.x} ${source.location.y} ${source.location.z} air`);
                        source.runCommand(`setblock ${source.location.x} ${source.location.y + 1} ${source.location.z} air`);
                        source.runCommand(`clear @s ${itemStack.typeId} 0 1`);
                        DATA_STRUCTURE[source.nameTag] = {
                            timer: system.currentTick,
                            cooldown: 13 * 20,
                            item_use: true
                        };
                    }
                    break;
                }
                case 1: {
                    break;
                }
            }
        });
    }
})

system.runInterval(() => {
    world.getAllPlayers().forEach((player) => { 
        const structure_timer = DATA_STRUCTURE[player.nameTag]?.timer ?? 0
        const structure_cooldown = DATA_STRUCTURE[player.nameTag]?.cooldown ?? 0
        const structure_item_use = DATA_STRUCTURE[player.nameTag]?.item_use ?? false
        if (structure_item_use) {
            if (system.currentTick > structure_cooldown + structure_timer) {
                
                player.camera.clear()
                delete DATA_STRUCTURE[player.nameTag];
            }
        }
    })
    
})

system.runInterval(() => {
    world.getAllPlayers().forEach((player) => {
        const itemId = WEAPONS_DATA[player.nameTag]?.itemId ?? 'minecraft:air'
        const timer = WEAPONS_DATA[player.nameTag]?.timer ?? 0
        const cooldown = WEAPONS_DATA[player.nameTag]?.cooldown ?? 0
        const item_use = WEAPONS_DATA[player.nameTag]?.item_use ?? false

        if (item_use) {
            if (system.currentTick > cooldown + timer) {
                scanerMobs(player,{
                    tags: [player.nameTag],
                    maxDistance: 1,
                    location: player.location
                }).forEach((victim) => {
                    victim.remove()
                })
                player.camera.clear()
                delete WEAPONS_DATA[player.nameTag];
            }
        }
        
        if (getItem(player, true).typeId == 'ns_ab:zombie_shield' || getItem(player, false).typeId == 'ns_ab:zombie_shield') {
            player.addEffect('resistance',100,{showParticles:false,amplifier:1})
            player.addEffect('regeneration',100,{showParticles:false,amplifier:0})
            
        }
        if (getItem(player,false).typeId == 'ns_ab:mothers_fang_dagger') {
            player.dimension.getEntities({
                location: player.location,
                maxDistance: 3
            }).forEach((target) => {
                let is_tamed = target.getComponent(EntityComponentTypes.IsTamed)
                if (!is_tamed && target != player && target.typeId != 'minecraft:item') target.addEffect('poison',100, { showParticles:true })
            })
        }
        const {item_helmet, item_chestplate, item_leggings, item_boots} = retorn_armor(player)
        if (
            item_helmet.typeId == 'ns_ab:dragon_helmet' && 
            item_chestplate.typeId == 'ns_ab:dragon_chestplate' && 
            item_leggings.typeId == 'ns_ab:dragon_leggings' && 
            item_boots.typeId == 'ns_ab:dragon_boots'
        ) {
            const view = player.getViewDirection()
            
            if (player.isJumping) {
                player.applyKnockback(0.2*view.x,0.2*view.z,1,0.5*view.y);
                player.addEffect('slow_falling',99999,{showParticles:false});
                player.playAnimation('animation.ns_ab.player_fly');
            }
            if (player.isOnGround) {
                player.removeEffect('slow_falling')
            }
            player.dimension.getEntities({
                maxDistance: 2,
                location: player.location,
            }).forEach((victim) => {
                let is_tamed = victim.getComponent(EntityComponentTypes.IsTamed);
                if (!is_tamed && player != victim && victim.typeId != 'minecraft:item' && victim.typeId != 'ns_ab:ice_spike') {
                    victim.setOnFire(5,true)
                }
            })
        }
    })
})

function use_ability(source, itemStack,timer,animation, vfx,cooldown, item_cooldown) {
    source.playAnimation(animation);
    let entity = source.dimension.spawnEntity(vfx,source.location);
    entity.setRotation(source.getRotation())
    entity.addTag(source.nameTag);
    entity.addTag('attack_1');
    WEAPONS_DATA[source.nameTag] = {
        itemId: itemStack.typeId,
        timer: system.currentTick,
        cooldown: timer*20,
        item_use: true
    };
    if (cooldown == 0) source.startItemCooldown(item_cooldown,timer*20);
}

function fire_impact(source) {
    let { location } = source
    let { x, y, z } = location

    for(var r = 2; r < 13; r++) {
        mkCircle( r ).forEach(e=> {
            const ex = e[0]
            const ez = e[1]

            system.runTimeout(()=> {
                const nl = { x: ex+x, y: y+Math.abs(Math.random()*2.0), z: ez+z}
                source.dimension.getEntitiesAtBlockLocation(nl).forEach(e=>{
                    const is_tamed = e.getComponent(EntityComponentTypes.IsTamed)
                    const has_tag_equal_nameTag = e.hasTag(source.nameTag)
                    if(!is_tamed && e != source && !has_tag_equal_nameTag)
                        e.setOnFire( 5, true)
                })
            }, r)
        })
    }
}

function mkCircle( r ){
    let N = 2*r+1
    let x, y
    let out = []

    for (let i = 0; i < N; i++) {
        for (let j = 0; j < N; j++) {
            x = i - r;
            y = j - r;
   
            if (x * x + y * y <= r * r + 1 )
                out.push([x, y])
        }
    }

    return out
}

function camera(source) {
    const view = source.getViewDirection()
    source.camera.setCamera('minecraft:third_person')
}

/**
 * 
 * @param {Player} source 
 * @returns 
 */
function retorn_armor(source) {
    const item_helmet = ((source.getComponent(EntityComponentTypes.Equippable)?.getEquipment(EquipmentSlot.Head)) ?? new ItemStack( "air", 1))
    const item_chestplate = ((source.getComponent(EntityComponentTypes.Equippable)?.getEquipment(EquipmentSlot.Chest)) ?? new ItemStack( "air", 1))
    const item_leggings = ((source.getComponent(EntityComponentTypes.Equippable)?.getEquipment(EquipmentSlot.Legs)) ?? new ItemStack( "air", 1))
    const item_boots = ((source.getComponent(EntityComponentTypes.Equippable)?.getEquipment(EquipmentSlot.Feet)) ?? new ItemStack( "air", 1))
    return {item_helmet: item_helmet, item_chestplate: item_chestplate, item_leggings: item_leggings, item_boots: item_boots}
}

function remove_tamed(source,mobs) {
    mobs.forEach((mob) => {
        scanerMobs(source,{
            location:source.location,
            maxDistance:40
        }).forEach((target) => {
            let is_tamed = target.getComponent(EntityComponentTypes.IsTamed);
            if (is_tamed && target.typeId == `${mob}`) {
                target.remove()
            }
        })
    })
}