import {system, world, GameMode, StructureAnimationMode, EntityComponentTypes, Player, StructureRotation, ItemStack} from '@minecraft/server';
import { circuleParticle } from '../assistant/particle';
import {boss, distance, launchEntity, removerPrefixo, scanerMobs, spawnEntitiesInLine, spawnRandomMinions,WEAPONS,WEAPONS_DATA} from './communs';

const ignoreEntity = [
    'ns_ab:ice_spike',
    'minecraft:lightning_bolt',
    "minecraft:item",
    "minecraft:ender_crystal",
    "minecraft:tnt",
    "minecraft:command_block_minecart",
    "minecraft:minecart",
    "minecraft:hopper_minecart",
    "minecraft:tnt_minecart",
    "minecraft:chest_minecart",
    "minecraft:chest_boat",
    "minecraft:boat",

    "minecraft:arrow",
    "minecraft:snowball",
    "minecraft:fireball",
    "minecraft:small_fireball",
    "minecraft:dragon_fireball",
    "minecraft:fishing_hook",
    "minecraft:wither_skull_dangerous",
    "minecraft:wither_skull",
    "minecraft:xp_orb",
    "minecraft:xp",
    "minecraft:xp_bottle",
    "minecraft:lingering_potion",
    "minecraft:splash_potion",
    "minecraft:wind_charge_projectile_potion",

    "ns_ab:vfx_dd_1",
    "ns_ab:vfx_dd_2",
    "ns_ab:vfx_fire_1",
    "ns_ab:vfx_fire_2",
    "ns_ab:vfx_lighting_1",
    "ns_ab:vfx_lighting_2",
    "ns_ab:vfx_nk_1",
    "ns_ab:vfx_nk_2",
    "ns_ab:vfx_sd_1",
    "ns_ab:vfx_water_1",
    "ns_ab:vfx_water_2",

    "minecraft:villager_v2",
    "ns_ab:guidebook"
]

system.afterEvents.scriptEventReceive.subscribe((event)=> {
    const {
        id, sourceEntity, message,
        sourceType, initiator, sourceBlock
    } = event;
    try {
        const sourceLocation = sourceEntity?.location

        let mobs = scanerMobs(sourceEntity,{
            maxDistance: 20,
            location: sourceLocation,
            families:["player"],
            closest: 1,
            tags:["gmsurvival"]
        })
        switch (id) {
            case 'ns_ab:knockback': {
                let mobs = scanerMobs(sourceEntity,{
                    maxDistance:10,
                    location:sourceLocation,
                    tags:["gmsurvival"]
                })
                mobs.forEach((victim) => {
                    if (victim.id != sourceEntity.id) {
                        let distanceEV = distance(sourceEntity, victim)
                        let ak = message*(distanceEV >= 8 && distanceEV <= 10 ? 1 : (distanceEV >= 3 && distanceEV <= 7.9 ? 1.5 : 2.5));
                        victim.applyKnockback(ak,ak,ak,ak)
                    }
                })
                break;
            }
            case 'ns_ab:particle': {
                circuleParticle(sourceEntity,10)
                break;
            }
            case 'ns_ab:launch':{
                if (mobs.length > 0)
                    mobs.forEach((player) => {
                        launchEntity('ns_ab:minion_zombie',sourceEntity,player,6.5,-1,{x:-0.8,y:6,z:0});
                    });
                break
            }
            case 'ns_ab:shuriken':{
                if (mobs.length > 0)
                    mobs.forEach((player) => {
                        launchEntity('ns_ab:shuriken',sourceEntity,player,5,0,{x:0,y:1.8,z:0});
                    });
                break
            }
            case 'ns_ab:teleport': {
                if (mobs.length > 0)
                    mobs.forEach((player) => {
                        let location = player.location;
                        let offsetX = Math.floor(Math.random() * 3) - 2;
                        let offsetZ = Math.floor(Math.random() * 3) - 2;
                        let tpPos = {
                            x: location.x + offsetX,
                            y: location.y + 0.5,
                            z: location.z + offsetZ,
                        }
                        if (player.dimension.getBlock(tpPos).typeId == 'minecraft:air') {
                            sourceEntity.addEffect('invisibility',100,{showParticles:false})
                            sourceEntity.tryTeleport(tpPos)
                            sourceEntity.setProperty('ns_ab:invisibility',1)
                        } else return
                    })
                break
            }
            case 'ns_ab:dash': {
                sourceEntity.setProperty('ns_ab:raijin_armor',1)
                if (mobs.length > 0)
                    mobs.forEach((player) => {
                        const newLocation = {
                            x: player.location.x - sourceLocation.x,
                            y: player.location.y - sourceLocation.y,
                            z: player.location.z - sourceLocation.z,
                        };
                        sourceEntity.applyImpulse(newLocation)
                    })
                break
            }
            case 'ns_ab:raijin_push': {
                sourceEntity.runCommand(`fill ~-2~-1~-2 ~2~2~2 air replace fire`)
                let mobs = scanerMobs({
                    maxDistance: 10,
                    location: sourceLocation,
                    families:["player"],
                    tags:["gmsurvival"]
                })
                mobs.forEach((player) => {
                    player.teleport(sourceEntity.location)
                })
                break
            }
            case 'ns_ab:ice_spike': {
                if (mobs.length > 0)
                    mobs.forEach((player) => {
                        sourceEntity.addTag('owner')
                        spawnEntitiesInLine("ns_ab:ice_spike", sourceLocation, player.location, player)
                    })
                break
            }
            case "ns_ab:web_ms": {
                if (mobs.length > 0)
                    mobs.forEach((player) => {
                        launchEntity('ns_ab:web',sourceEntity,player,5,0,{x:0,y:1.8,z:0});
                    });
                break
            }
            case "ns_ab:mother_spider_attack": {
                sourceEntity.playAnimation('animation.giant_spider.attack')
                sourceEntity.getEntitiesFromViewDirection({maxDistance:7}).forEach((target) => {
                    if(!ignoreEntity.includes(target.entity.typeId))
                    target.entity.applyDamage(6)
                })
                sourceEntity.setProperty('ns_ab:cooldown',1)
                break
            }
            case "ns_ab:shoot_dragon": {
                if ( sourceEntity.getProperty('ns_ab:cooldown_time') == 0 && sourceEntity.getProperty('ns_ab:alive')) {
                    if (mobs.length > 0)
                        mobs.forEach((player) => {
                            sourceEntity.playAnimation('animation.dragon_fire.attack_1');
                            launchEntity('ns_ab:fireball',sourceEntity,player,5,0,{x:0,y:1.8,z:0});
                        });
                    sourceEntity.setProperty('ns_ab:cooldown_time',5);
                }
                break
            }
            case "ns_ab:fireball_scna": {
                if ( !sourceEntity.hasTag('target_ok')){
                    let mobs = scanerMobs(sourceEntity,{
                        families:["player"],
                        closest:1,
                        location:sourceLocation,
                        maxDistance:2,
                        tags:["gmsurvival"]
                    })
                    mobs.forEach((target) => {
                        const view = target.getViewDirection()
                        target.applyKnockback(view.x*-0.2,view.x*-0.2,1,1);
                        target.applyDamage(3);
                    })
                } 
                break
            }
            case 'ns_ab:nk_evoker': {
                spawnRandomMinions(["ns_ab:skeleton_sword","ns_ab:skeleton_bow"],sourceEntity,sourceEntity)
                break
            }
            case 'ns_ab:nk_buffs': {
                sourceEntity.removeTag('spawn_minions')
                let mobs = scanerMobs(sourceEntity,{
                    maxDistance: 20,
                    location: sourceLocation,
                    tags: [`${sourceEntity.id}`]
                })
                if (mobs.length > 0) {
                    mobs.forEach((minion) => {
                        if (minion.typeId == "ns_ab:minion_zombie") return
                        else {
                            minion.setProperty('ns_ab:beserk', 1)
                        }
                    })
                }
                break
            }
            case 'ns_ab:attack_red_katana': {
                scanerMobs(sourceEntity,{
                    families:["player"],
                    maxDistance: 7,
                    location: sourceLocation
                }).forEach((player) => {
                    if (sourceEntity.hasTag(player.nameTag)) {
                        const itemId = WEAPONS_DATA[player.nameTag]?.itemId ?? 'minecraft:air';
                        const { damage, on_fire, item_cooldown, timer, } = WEAPONS[itemId]
                        
                        player.getEntitiesFromViewDirection({
                            excludeTags:[`${player.nameTag}`],
                            maxDistance: 7
                        }).forEach((target) => {
                            if ((target.entity.typeId != "minecraft:item" || target.entity != sourceEntity) && !ignoreEntity.includes(target.entity.typeId)) {
                                let entityLocation = target.entity.location;
                                let entity = target.entity
                                entity.teleport(entityLocation)

                                if (on_fire) entity.setOnFire(3,true);
                                else entity.extinguishFire(true)
                                entity.applyDamage(damage);
                            }
                            
                        })
                    }
                })
                break
            }
            case 'ns_ab:tornado_fds': {
                scanerMobs(sourceEntity,{
                    families:["player"],
                    maxDistance: 7,
                    location: sourceLocation
                }).forEach((player) => {
                    if (sourceEntity.hasTag(player.nameTag)) {
                        const itemId = WEAPONS_DATA[player.nameTag]?.itemId ?? 'minecraft:air';
                        const { damage, on_fire, item_cooldown, timer, } = WEAPONS[itemId]
                        
                        scanerMobs(player,{
                            excludeTags: [`${player.nameTag}`],
                            maxDistance:5,
                            location: player.location,
                        }).forEach((target) => {
                            if (player.id != target.id && target.typeId != "minecraft:item") {
                                if (!on_fire) target.extinguishFire()
                                target.addEffect('levitation',20*3);
                                target.applyDamage(damage)
                            }
                        })
                    }
                })
                break
            }
            case 'ns_ab:teleport_owner': {
                scanerMobs(sourceEntity,{
                    families:["player"],
                    maxDistance: 20,
                    location: sourceLocation
                }).forEach((owner) => {
                    if (sourceEntity.hasTag(owner.nameTag)) {
                        sourceEntity.teleport(owner.location),
                        sourceEntity.setRotation(owner.getRotation())
                    }
                })
                break
            }
            case 'a:kill': {
                sourceEntity.dimension.getEntities({
                    maxDistance:10,
                    location:sourceLocation
                }).forEach((target) => {
                    target.remove()
                })
                break
            }
            case 'ns_ab:boss_fight_music': {
                if (boss[removerPrefixo(sourceEntity.typeId)]) {
                    sourceEntity.runCommand(`playsound ${boss[removerPrefixo(sourceEntity.typeId)].music} @a[r=20]`)
                }
                break
            }
            case 'ns_ab:stop_music': {
                if (boss[removerPrefixo(sourceEntity.typeId)]) {
                    sourceEntity.runCommand(`stopsound @a[r=20] ${boss[removerPrefixo(sourceEntity.typeId)].music} `)
                }
                break
            }
            case 'ns_ab:thunder': {
                scanerMobs(sourceEntity,{
                    location:sourceLocation,
                    maxDistance:7
                }).forEach((target) => {
                    let is_tamed = sourceEntity.getComponent(EntityComponentTypes.IsTamed);
                    let nameTag = target.nameTag
                    if (
                        !is_tamed && 
                        !sourceEntity.hasTag(`${nameTag}`) && 
                        target != sourceEntity && 
                        !ignoreEntity.includes(target.typeId)
                    ) {
                        target.dimension.spawnEntity('minecraft:lightning_bolt',target.location)

                    }
                })
                break
            }
            case "book:death": {
                let spawnEgg = new ItemStack(`${sourceEntity.typeId}_spawn_egg`)
                sourceEntity.dimension.spawnItem(spawnEgg,sourceLocation)
                sourceEntity.remove();
                break
            }
            case "ns_ab:knockback_dragon": {
                scanerMobs(sourceEntity,{
                    location: sourceLocation,
                    maxDistance: 4,
                    families: ["player"]
                }).forEach((player) => {
                    const view = player.getViewDirection();
                                
                    player.applyKnockback(
                        -0.2 * view.x,
                        -0.2 * view.z,
                        1.5,
                        0
                    );
                })
                break
            }
        }
    } catch (error) {
       return 
    }
    
})

/*
let structure = world.structureManager.get(
    `mystructure:bp_${idBackpack}_of_${source.id}`
);
world.structureManager.place(structure, source.dimension, location, {
    includeEntities: true,
});
world.structureManager.delete(
    `mystructure:bp_${idBackpack}_of_${source.id}`
);
*/