import * as mc from "@minecraft/server";
import stand from "./other.js";
import titleUI from "./standUI.js";
import Vec3 from "../../../modules/Vec3.js";
import range from "../../../modules/arrayRange.js";
import Mathf from '../../../modules/Mathf.js';
import registerSystem from "../../../register/registerSystem.js";

export default class stand_defaultAttack extends registerSystem {
    property(name) {
        return this.GlobalVar(this.standMaster,name);
    }
    global(name) {
        return this.GlobalVar(this.standMaster,name);
    }
    globalW(name) {
        return this.GlobalVar(mc.world,name);
    }
    constructor(player) {
        super();
        this.standMaster = player;
        
        this.skills_count = 2;
        
        this.health = this.standMaster.getComponent("minecraft:health");
        this.movement = this.standMaster.getComponent("minecraft:movement");
        this.inventory = this.standMaster.getComponent("minecraft:inventory").container;
        
        this.stand_range = this.scores(player,"stand_range");
        
        this.use_skill1 = this.getHandItem(player)?.typeId === "stand:skill1";
        this.use_skill2 = this.getHandItem(player)?.typeId === "stand:skill2";
        
        
        this.stand_pa = this.GlobalVar(this.standMaster,"stand_pa");
        this.slot_data = range(0,3).map(v => {
            return this.GlobalVar(this.standMaster,"stand_slotData" + v);
        })
        this.UIslotData = range(0,3).map(v => {
            return this.slot_data[v].var;
        })
        
        this.shealth = this.GlobalVar(this.standMaster,"standMaster.health");
        this.shealth_max = this.GlobalVar(this.standMaster,"standMaster.health_max");
        this.fist_duration = this.GlobalVar(this.standMaster,"stand_skill1");
        this.fist_duration2 = this.GlobalVar(this.standMaster,"stand_skill1_2");
        this.mental_value = this.GlobalVar(this.standMaster,"mental_value");
        this.mental_reply = this.GlobalVar(this.standMaster,"mental_reply");
        this.mental_timer = this.GlobalVar(this.standMaster,"mental_timer");
        this.barrage_camera_shake = this.GlobalVar(this.standMaster,"barrage_camera_shake");
        this.mental_infinite = this.GlobalVar(mc.world,"mental.is_infinite");
        this.mental_recovery = this.GlobalVar(mc.world,"mental.can_recovery");
        // this.fist_duration = this.property("stand_skill1");
        // this.fist_duration2 = this.property("stand_skill1_2");
        // this.mental_value = this.property("mental_value");
        // this.mental_reply = this.property("mental_reply");
        // this.mental_timer = this.property("mental_timer");
        // this.barrage_camera_shake = this.global("barrage_camera_shake");
        // this.mental_infinite = this.globalW("mental.is_infinite");
        // this.mental_recovery = this.globalW("mental.can_recovery");
        
        this.stand = /stand:skill1/;
        this.stand2 = /stand:\w+/;
        
        this.check = this.mental_value.var >= 0 && this.mental_value.var <= 70;
        
        this.customUI = new titleUI(this.standMaster);
        this.MentalPanelUI = () => {
            return 0;
        }
        this.LoadingGUI = (ui) => {
            return this.customUI.loadingGUI(ui);
        }
        this.LoadingUI2 = (ui) => {
            return this.customUI.loadingUI2(ui);
        }
        this.removeMentalValue = (value) => {
            this.MentalPanelUI();
            this.mental_value.var -= this.mental_infinite.var ? 0 : value;
            this.mental_reply.var = 0;
        }
        this.addMentalValue = (value) => {
            this.MentalPanelUI();
            this.mental_value.var += value;
            this.mental_reply.var = 0;
        }
        this.removeHealth = (value) => {
            if (this.shealth.var >= 0) {
                this.shealth.var = Mathf.clamp(this.shealth.var - value, 0, this.shealth_max.var);
            } else {
                this.health.setCurrentValue(this.health.currentValue - value);
            }
        }
        this.addHealth = (value) => {
            if (this.shealth.var >= 0) {
                this.shealth.var = Mathf.clamp(this.shealth.var + value, 0, this.shealth_max.var);
            } else {
                this.health.setCurrentValue(this.health.currentValue + value);
            }
        }
        /*
        if (this.check && this.mental_reply.var <= (70 - this.mental_value.var + 10) * 15) {// (70-30+10)*10
            this.mental_reply.var += this.mental_recovery.var ? 1 : 0;
        } else if (this.check) {
            this.mental_reply.var = 0;
            this.mental_value.var += 1;
        }*/

        this.main();
        
    }
    
    main() {
        let player = this.standMaster;
        let handItem = this.getHandItem(player);
        let itemTag = JSON.stringify({
            "minecraft:item_lock": {
                mode: "lock_in_inventory"
            }
        });
        player?.addEffect("jump_boost",20,{
            amplifier: 1,
            showParticles: false
        });
        /*
        if (handItem?.typeId === "minecraft:diamond_sword") {
            player?.applyKnockback(0,0,0,-3)
        }*/
        


        if (handItem?.typeId === "stand:skill1") {
            player?.addTag("stand.pAmode");
            this.runCommand(`effect @s weakness 9999 255 true`, player);
        } else {
            this.runCommand(`effect @s[tag=stand.pAmode] weakness 0 0 true`, player);
            player?.removeTag("stand.pAmode")
        }
        
        if (this.shealth.var > 0) {
            this.health.setCurrentValue(this.health.defaultValue);
            // player?.addEffect("resistance",20,{
                // amplifier: 255,
                // showParticles: false
            // });
        }
        if (this.mental_timer.var == 0 || this.mental_timer.var == 3) {
            this.MentalPanelUI();
        }
        let skills = range(1,this.skills_count).map(v => {
            return `{item=stand:skill${v},quantity=0}`
        }).join(",");
        this.runCommand(`tag @s[hasitem=[${skills}]] add stand.no_skills`, player);
        if (player?.hasTag("stand.no_skills")) {
            for (let i of range(1,this.skills_count)) {
                let inventory = player?.getComponent("inventory").container;
                let itemStack = new mc.ItemStack(mc.ItemTypes.get("stand:skill" + i));
                itemStack.keepOnDeath = true,
                itemStack.lockMode = "inventory",
                inventory?.addItem(itemStack)
            }
            player?.removeTag("stand.no_skills");
        }
    }
    
    set_stand_range(target,range) {
        let player = this.standMaster;
        let playerPos = "xyz".split("").map(xyz => {
            return player?.location[xyz];
        });
        let targetPos = "xyz".split("").map(xyz => {
            try {
                return target?.location[xyz]
            } catch(e) {
                return target[xyz]
            }
        });
        let distance = new Vec3(...targetPos).Distance(...playerPos);
        let value = Mathf.clamp(distance.toFixed(2) * 100, 80, range * 100)
        this.stand_range.var = value
    }
    
    set_stand_range2(target) {
        let player = this.standMaster;
        let playerPos = "xyz".split("").map(xyz => {
            return player?.location[xyz];
        });
        let targetPos = "xyz".split("").map(xyz => {
            try {
                return target?.location[xyz]
            } catch(e) {
                return target[xyz]
            }
        });
        let distance = new Vec3(...targetPos).Distance(...playerPos);
        let value = Math.max(80, distance.toFixed(2) * 100)
        this.stand_range.var = value
    }
    
    broadcastAnim(name) {
        let player = this.standMaster;
        let arrow = "->";
        let startsName = name.split(arrow)[0];
        let endsName = name.split(arrow)[1];
        return this.runCommand(`playanimation @s animation.${startsName}.variable_create.${endsName} default 1`, player);
    }
    removeAnim(name) {
        let player = this.standMaster;
        let arrow = "->";
        let startsName = name.split(arrow)[0];
        let endsName = name.split(arrow)[1];
        return this.runCommand(`playanimation @s animation.${startsName}.variable_remove.${endsName} default 1`, player);
    }
    
    summon(data) {
        let player = this.standMaster;
        let handItem = this.getHandItem(player);
        
        if (this.stand.exec(handItem.typeId) && !player?.hasTag("stand.summon") && this.mental_value.var > 0) {
            data.sounds.forEach(sound => {
                this.runCommand(`playsound ${sound} @a[tag=!entity.in_timeErase,r=10] ~ ~ ~`, player);
            })
            this.broadcastAnim(`stand->summon.${data.anim_id}`);
            player?.addTag("stand.summon");
        } else if ((!this.stand2.exec(handItem.typeId) || this.mental_value.var <= 0) && player?.hasTag("stand.summon")) {
            this.removeAnim("stand->remove");
            this.runCommand(`playsound stand.remove @a[tag=!entity.in_timeErase,r=10] ~ ~ ~`, player);
            player?.removeTag("stand.summon");
        }
    }
    
    
    defaultAttack(data) {
        let player = this.standMaster;
        if (!player?.hasTag("stand.fist_isCooldown") && this.fist_duration.var > 0 && this.mental_value.var > 0) {
            let lc = this.getLc(player);
            if (player?.hasTag("stand.pa")) {
                this.fist_duration.var = Math.max(0, this.fist_duration.var - data.loss);
                this.fist_duration2.var = 0;
                player?.addTag("stand.pa_stage");
                if (!player?.hasTag("stand.pa_interval")) {
                    this.stand_pa.var += 1;
                    this.broadcastAnim(`stand->pa${this.stand_pa.var}`)
                    this.runCommand(`playsound ${data.sound1} @a ~ ~ ~`, player);
                    if (this.stand_pa.var === data.max_fist_count && data.sound2 !== undefined) {
                        this.runCommand(`playsound ${data.sound2} @a ~ ~ ~`, player);
                    }
                    let hitEntities = this.getEntities({tags:["stand.damageBy:" + player?.nameTag]});
                    if (hitEntities.length > 0) {
                        hitEntities.forEach(entity => {
                            let strength_effect = player?.getEffect("strength");
                            let damage = data.damage + (strength_effect === undefined ? 0 : strength_effect?.amplifier) + (this.stand_pa.var === data.max_fist_count) * 2
                            let hitVector = "xyz".split("").map(xyz => {
                                return this.stand_pa.var === 4 && xyz === "y" ? data.power * 2 : lc[xyz] * data.power;
                            })
                            this.set_stand_range2(entity);
                            // console.error(this.stand_range.var / 100)
                            
                            if (entity?.hasTag("entity.in_timeStop")) {
                                entity?.addTag(`overlayDamage`);
                                
                                let overlayVelocity = Object.fromEntries("xyz".split("").map(xyz => {
                                    return [ xyz, {var:0} ]
                                }))
                                "xyz".split("").map((xyz,index) => {
                                    try {
                                        overlayVelocity[xyz] = this.scores(entity,"overlayVelocity" + xyz.toUpperCase());
                                    } catch(e) {
                                        overlayVelocity[xyz] = {
                                            var: 0
                                        }
                                    }
                                    overlayVelocity[xyz].var = hitVector[index].toFixed(2) * 100
                                })
                                
                                
                                let overlayDamage = {
                                    var: 0
                                }
                                try {
                                    overlayDamage = this.scores(entity,"overlayDamage");
                                } catch(e) {
                                    overlayDamage = {
                                        var: 0
                                    }
                                }
                                overlayDamage.var += damage;
                            } else {
                                if (!entity?.hasComponent("minecraft:movement") || this.stand_pa.var === 4) {
                                    this.runCommand(`damage @s 0 suicide entity @a[name="${player?.name}"]`, entity);
                                } else {
                                    this.runCommand(`damage @s[type=!ender_dragon] ${damage} suicide`, entity);
                                    this.runCommand(`damage @s[type=ender_dragon] ${damage} suicide entity @a[name="${player?.name}"]`, entity);
                                }
                                if (entity?.typeId === "minecraft:player") {
                                    entity?.applyKnockback(lc.x, lc.z, 0 + (this.stand_pa.var !== data.max_fist_count) * data.power * this.getLc2(-90,0).y - Math.abs(Math.round(player?.getViewDirection().y)), 0 + (this.stand_pa.var === data.max_fist_count) * data.power * 2.3)
                                } else {
                                    entity?.applyImpulse(new Vec3(...hitVector).Vector());
                                }
                            }
                            this.runCommand(`effect @s[type=!player] slowness 1 3 true`, entity);
                            entity?.removeTag("stand.damageBy:" + player?.nameTag)
                        })
                    }
                }
                player?.addTag("stand.pa_interval")
                player?.removeTag("stand.pa")
            }
            if (player?.hasTag("stand.pa_stage")) {
                this.fist_duration2.var += 1;
                if (this.fist_duration2.var >= 2 && this.stand_pa.var === data.max_fist_count) {
                    player?.addTag("stand.stop_pa")
                    this.removeMentalValue(data.mental);
                }
                if (this.fist_duration2.var >= data.attack_interval) {
                    player?.removeTag("stand.pa_interval")
                }
                if (this.fist_duration2.var >= data.delay || player?.hasTag("stand.stop_pa")) {
                    this.removeAnim("stand->pa")
                    this.stand_pa.var = 0;
                    this.fist_duration2.var = 0;
                    player?.addTag("stand.fist_isCooldown");
                    player?.removeTag("stand.pa_interval");
                    player?.removeTag("stand.pa_stage");
                    player?.removeTag("stand.stop_pa");
                }
            }
        } else {
            if (player?.hasTag("stand.pa")) {
                player?.removeTag("stand.pa_interval");
                player?.removeTag("stand.pa_stage");
                player?.removeTag("stand.stop_pa");
                player?.removeTag("stand.pa");
            }
        }
        
    }
    
    quickFist(data, functions_data = { ticking: (...args) => {return null}, onHitEntity: (...args) => {return null} }) {
        let tag = "替身连打攻击";
        
        let player = this.standMaster;
        
        let handItem = this.getHandItem(player);
        
        this.slot_data[0].var = [
            this.use_skill1 && !player?.isSneaking,
            (this.fist_duration.var / 20).toFixed(1),
            data.duration,
            NaN
        ].join("|")
        // functions_data.ticking(data)
        
        if (!player?.hasTag("stand.pa") && !player?.hasTag("stand.hit") && !player?.hasTag("stand.fist_isCooldown") && player?.hasTag("stand.quick_fist") && this.mental_value.var > 0 && this.fist_duration.var > 0 && this.fist_duration.var <= data.duration * 20) {
            this.fist_duration.var -= 1;
        }
        if (!player?.hasTag("stand.hit") && player?.hasTag("stand.fist_isCooldown") && this.mental_value.var > 0 && this.fist_duration.var >= 0 && this.fist_duration.var < data.duration * 20) {
            this.fist_duration.var = Math.min(this.fist_duration.var + data.cooldown_reply, data.duration * 20);
            if (this.fist_duration.var < data.duration * 20) {
                player?.removeTag("stand.quick_fist");
            }
        }
        
        if (this.fist_duration.var >= data.duration * 20) {
            player?.removeTag("stand.fist_isCooldown");
        }
        
        if (!player?.hasTag("stand.hit") && !player?.hasTag("stand.fist_isCooldown") && player?.hasTag("stand.quick_fist") && this.fist_duration.var > 0 && this.mental_value.var > 0) {
            
            player?.removeTag("stand.stop_fist");
            this.fist_duration2.var += 1;
            
            if (this.fist_duration2.var == 1) {
                this.broadcastAnim(`stand->quick_fist`);
                if (this.barrage_camera_shake.var) {
                    this.runCommand(`camerashake add @s 0.5 5`, player)
                }
            }
            stand.fist(this, player, data, {
                repel: 0.1,
                damage: data.damage,
                once_sound: "play",
                fist_sound: "play",
                hit_sound: "stop",
                condition: {
                    mental_value: this.fist_duration2.var % data.mental.interval == 0,
                    attack_entity: this.fist_duration2.var == 0 || this.fist_duration2.var == 1 || this.fist_duration2.var % 4 == 0,
                    hit_projectile: this.fist_duration2.var == 0 || this.fist_duration2.var == 1 || this.fist_duration2.var % 1 == 0
                }
            })
        }
        if ((player?.hasTag("stand.quick_fist") && this.fist_duration.var <= 0) || (!player?.hasTag("stand.quick_fist") && !player?.hasTag("stand.pa"))) {
            if (!player?.hasTag("stand.pa_stage") && !player?.hasTag("stand.hit") && this.fist_duration2.var > 0) {
                this.fist_duration2.var = 0;
                player?.addTag("stand.hit");
                player?.addTag("stand.fist_isCooldown");
                this.runCommand(`camerashake stop @s`, player)
                this.removeAnim("stand->quick_fist");
                stand.fist(this, player, data, {
                    repel: 3,
                    damage: data.damage + 2,
                    fist_sound: "stop",
                    hit_sound: "play",
                    condition: {
                        mental_value: true,
                        attack_entity: true,
                        hit_projectile: true
                    }
                },functions_data)
            } 
            if (player?.hasTag("stand.hit")) {
                this.fist_duration2.var += 1;
                if (this.fist_duration2.var >= 15) {
                    let attackedEntityTag = "isAttackedByFist";
                    let attackedProjectileTag = "isHitByFist";
                    player?.removeTag("stand.quick_fist");
                    player?.removeTag("stand.hit");
                    this.runCommands([
                        `tag @e[tag=${attackedEntityTag}] remove ${attackedEntityTag}`,
                        `tag @e[tag=${attackedProjectileTag}] remove ${attackedProjectileTag}`
                    ], player);
                    this.fist_duration2.var = 0;
                    this.stand_range.var = 80;
                }
            }
        }
    }
    
}
