import * as mc from "@minecraft/server";
import Vec3 from "../../../modules/Vec3.js";
import range from "../../../modules/arrayRange.js";
import Mathf from '../../../modules/Mathf.js';

export default class stand {
    static sound(system,mode,type,data) {
        let player = system.standMaster
        if (data[type] !== undefined) {
            for (let i in data[type]) {
                let sound = {
                    name: data[type][i].split("->")[0],
                    interval: parseInt(data[type][i].split("->")[1])
                };
                let sound_type = (type) => {
                    let sound_mode = {
                        once: `playsound ${sound.name} @a ~ ~ ~`,
                        play: `playsound ${sound.name} @a ~ ~ ~`,
                        stop: `stopsound @a ${sound.name}`
                    }
                    return sound_mode[type]
                }
                switch (mode) {
                    case "once":
                        if (mode !== undefined && (system.fist_duration2.var == 0 || system.fist_duration2.var == 1)) {
                            system.runCommand(sound_type("once"), player);
                        }
                        break;
                    case "play":
                        if (system.fist_duration2.var == 0 || system.fist_duration2.var == 1 || system.fist_duration2.var % sound.interval == 0) {
                            system.runCommand(sound_type("play"), player);
                        }
                        break;
                    case "stop":
                        system.runCommand(sound_type("stop"), player);
                        break;
                }
                
            }
        }
    }
    static fist(system, source, data, fist_data, functions_data = { ticking: (...args) => {return null}, onHitEntity: (...args) => {return null} }) {
        let lc = system.getLc(source);
        let attackedEntityTag = "isAttackedByFist";
        let attackedProjectileTag = "isHitByFist";
        let stand_range = data.range + system.GlobalVar(mc.world,"stand_range_limit").var;
        
        // for (let i of range(2, (stand_range + 1) * 12 * 0.1)) {
        for (let i of range(2, stand_range + 2)) {
        // if (system.fist_duration2.var >= 0) {
            // system.stand_range.var = Mathf.clamp(system.fist_duration2.var + 2, 2, stand_range + 2) * 100;
            // let i = system.stand_range.var / 100;
            let pos = "xyz".split("").map(xyz => {
                let value = Math.round(i * lc[xyz]);
                return "~" + value;
            }).join(" ");
            let attack_range = (r,tag,y) => {
                return `execute positioned ${pos} as @s run tag @e[type=!goldexperience:tree,name=!"${source.name}",r=${r}] add ${tag}`
            };
            
            system.runCommands([
                attack_range(1.12,attackedEntityTag),
                // attack_range(1.12,attackedEntityTag,1),
                attack_range(1.65,attackedProjectileTag)
            ], source);
            
            system.getEntitiesFromViewVector(source, 1).forEach(entity => {
                entity.entity.addTag(attackedEntityTag);
            })
        }
        
        
        if (fist_data.condition.mental_value) {
            system.removeMentalValue(data.mental.value);
        }
        
        let default_fist_sound = `playsound game.player.attack.strong @a ~ ~ ~`;
        system.runCommand(default_fist_sound, source);
        this.sound(system,fist_data.once_sound,"once_sounds",data);
        this.sound(system,fist_data.fist_sound,"fist_sounds",data);
        this.sound(system,fist_data.hit_sound,"hit_sounds",data);
        
        
        // if (fist_data.condition.attack_entity) {
        if (true) {
            let attackedEntity = system.getEntities({tags:[attackedEntityTag]}).filter(e => (e?.hasComponent("movement") || e?.id == "minecraft:armor_stand" || e?.id == "minecraft:boat" || e?.id == "minecraft:minecart"));
            if (attackedEntity.length <= 0) {
                let block = system.getBlockFromViewVector(source, stand_range + 3, {liquid: false, passable: false});
                if (block !== undefined && block !== null) {
                    let blockPos = block.location;
                    let playerPos = source.location;
                    system.set_stand_range(block,stand_range);
                }
            } else {
                attackedEntity.forEach(entity => {
                    system.set_stand_range(entity,stand_range);
                    if (fist_data.condition.attack_entity) {
                        let strength_effect = source?.getEffect("strength");
                        let power = fist_data.repel;
                        let damage = fist_data.damage + (strength_effect === undefined ? 0 : strength_effect?.amplifier)
                        let health = entity.getComponent("minecraft:health");
                        
                        functions_data.onHitEntity(source, data, fist_data, entity);
                        
                        if (entity?.hasTag("entity.in_timeStop")) {
                            entity?.addTag(`overlayDamage`);
                            
                            let overlayKnockback = Object.fromEntries("xzvh".split("").map(xzvh => {
                                return [ xzvh, {var:0} ]
                            }))
                            let overlayVelocity = Object.fromEntries("xyz".split("").map(xyz => {
                                return [ xyz, {var:0} ]
                            }))
                            if (entity?.typeId === "minecraft:player") {
                                "xzvh".split("").map(xzvh => {
                                    try {
                                        overlayKnockback[xzvh] = system.scores(entity,"overlayKnockback" + xzvh.toUpperCase());
                                    } catch(e) {
                                        overlayKnockback[xzvh] = {
                                            var: 0
                                        }
                                    }
                                })
                                overlayKnockback.x.var = lc.x * 100
                                overlayKnockback.z.var = lc.z * 100
                                overlayKnockback.v.var = (1.75 * power * system.getLc2(-90,0).y - Math.abs(Math.round(source.getViewDirection().y))) * 100
                                overlayKnockback.h.var = (source.getViewDirection().y * power * 1.75) * 100
                            } else {
                                "xyz".split("").map(xyz => {
                                    try {
                                        overlayVelocity[xyz] = system.scores(entity,"overlayVelocity" + xyz.toUpperCase());
                                    } catch(e) {
                                        overlayVelocity[xyz] = {
                                            var: 0
                                        }
                                    }
                                    overlayVelocity[xyz].var = (lc[xyz] * power).toFixed(2) * 100
                                })
                            }
                            
                            
                            let overlayDamage = {
                                var: 0
                            }
                            try {
                                overlayDamage = system.scores(entity,"overlayDamage");
                            } catch(e) {
                                overlayDamage = {
                                    var: 0
                                }
                            }
                            overlayDamage.var += damage;
                        } else {
                            let command1a = `damage @s[type=!ender_dragon] ${damage} suicide`;
                            let command1b = `damage @s[type=!ender_dragon] ${damage} entity_attack entity @a[name="${source.name}"]`;
                            let command2 = `damage @s[type=ender_dragon] ${damage} suicide entity @a[name="${source.name}"]`;
                            let command3 = `effect @s[type=!player] slowness 1 10 true`;
                            system.runCommands([
                                health.currentValue <= damage ? command1b : command1a,
                                command2,
                                command3
                            ], entity);
                            if (entity?.typeId === "minecraft:player") {
                                if (entity?.hasTag("kingCrimson.epitaph")) {
                                    let epitaph_position = system.GlobalVar(entity,"epitaph_position")
                                    let epitaph_vector = system.GlobalVar(entity,"epitaph_vector")
                                    let entity_pos = "xyz".split("").map(xyz => {
                                        return entity?.location[xyz].toFixed(3);
                                    })
                                    let entity_vec = "xyz".split("").map(xyz => {
                                        return system.getLc(entity)[xyz].toFixed(3);
                                    })
                                    epitaph_position.var = entity_pos.join("|");
                                    epitaph_vector.var = entity_vec.join("|");
                                    entity?.addTag("kingCrimson.avoid.stand");
                                } else {
                                    entity?.applyKnockback(lc.x, lc.z, 1.75 * power * system.getLc2(-90,0).y - Math.abs(Math.round(source.getViewDirection().y)), source.getViewDirection().y * power * 1.75);
                                }
                            } else {
                                entity?.applyImpulse(new Vec3(lc.x * power, lc.y * power, lc.z * power).Vector());
                            }
                        }
                        entity?.removeTag(attackedProjectileTag);
                        entity?.removeTag(attackedEntityTag);
                    }
                    
                    
                        
                })
                
            }
        }
        if (fist_data.condition.hit_projectile) {
            let projectiles = system.getEntities({tags:[attackedProjectileTag]}).filter(e => !e?.hasComponent("minecraft:movement") && e?.id != "minecraft:armor_stand" && e?.id != "minecraft:boat" && e?.id != "minecraft:minecart" && e?.id != "minecraft:item");
            if (projectiles.length > 0) {
                projectiles.forEach(entity => {
                    let power = Math.floor(Mathf.random(2,4));
                    let velocity = {
                        x: lc.x * power + Math.round(Mathf.random(-1,1)),
                        y: lc.y * power - 0.5,
                        z: lc.z * power + Math.round(Mathf.random(-1,1))
                    }
                    /*
                    let check3 = entity?.getTags().filter(tag => tag?.includes("gV_"))[0].replace(/gV_/,"").split("_");
                    check3.forEach(value => {
                        entity?.removeTag(value)
                    })
                    */
                    if (entity?.hasTag("entity.in_timeStop")) {
                        let overlayVelocity = Object.fromEntries("xyz".split("").map(xyz => {
                            return [ xyz, {var:0} ]
                        }))
                        "xyz".split("").map(xyz => {
                            try {
                                overlayVelocity[xyz] = system.scores(entity,"overlayVelocity" + xyz.toUpperCase());
                            } catch(e) {
                                overlayVelocity[xyz] = {
                                    var: 0
                                }
                            }
                            overlayVelocity[xyz].var = velocity[xyz].toFixed(2) * 100
                        })
                    }
                    let applyImpulse = "xyz".split("").map(xyz => {
                        return velocity[xyz];
                    })
                    entity?.applyImpulse(new Vec3(...applyImpulse).Vector());
                    entity?.removeTag(attackedProjectileTag);
                    entity?.removeTag(attackedEntityTag);
                })
            }
        }
    }
}