import * as mc from '@minecraft/server';
import stand_defaultAttack from '../default/stand_defaultAttack.js';
import titleUI from "../default/standUI.js";
import titleUIList from './_ui_/titleUIList.js';
import Vec3 from '../../../modules/Vec3.js';
import range from '../../../modules/arrayRange.js';
import Mathf from '../../../modules/Mathf.js';

export default class theWorld extends stand_defaultAttack {
    constructor(player) {
        super(player);
        this.standMaster = player;
        this.UI = titleUIList.ui;
        this.GUI = titleUIList.gui;
        
        this.timeStopColor = this.GlobalVar(this.standMaster,"timeStopColor");
        this.itemUseEvent = this.GlobalVar(mc.world,"itemUseEvent");
        
        this.stand_pa = this.GlobalVar(this.standMaster,"stand_pa");
        
        this.stop_tick = this.GlobalVar(this.standMaster,"stand_skill2");
        this.stop_tick2 = this.GlobalVar(this.standMaster,"stand_skill2_2");
        
        this.move_cd = this.GlobalVar(this.standMaster,"stand_skill3");
        
        this.ticking();
        // this.getPressurePlateMaterial = new Array("acacia", "birch", "crimson", "dark_oak", "heavy_weighted", "jungle", "light_weighted", "polished_black_stone", "spruce", "stone", "warped", "wooden");
    }
    
    ticking() {
        
        let player = this.standMaster;
        let handItem = this.getHandItem(player);
        // console.error(UIslotData)
        
        this.skills_count = 2;
        
        this.slot_data[3].var = [
            false,
            1,
            1,
            NaN
        ].join("|")

        this.LoadingGUI({
            name: "theWorld",
            value: this.UIslotData
        });
        
        if (!player?.hasTag("entity.in_timeStop")) {
            this.summon({
                anim_id: "the_world",
                sounds: [
                    "Diego.theWorld.name",
                    "Diego.theWorld.summon"
                ]
            });
            if (!player?.hasTag("theWorld.stop_barrage_attack")) {
                this.quickFist({
                    range: 4,
                    damage: 5,
                    duration: 4,
                    cooldown_reply: 3,
                    once_sounds: [
                        "Diego.mudadamuda->999"
                    ],
                    fist_sounds: [
                        "theWorld.fist->2"
                    ],
                    hit_sounds: [
                        "kingCrimson.punch->20"
                    ],
                    mental: {
                        value: 1,
                        interval: Math.floor(Mathf.random(40,60))
                    }
                });
                this.quickMove({
                    cooldown: 3,
                    range: 15,
                    mental: Math.floor(Mathf.random(3,4))
                });
                this.defaultAttack({
                    damage: 5,
                    attack_interval: 3,
                    delay: 5,
                    power: 0.25,
                    max_fist_count: 4,
                    mental: 1,
                    loss: 8,
                    sound1: "kingCrimson.punch",
                    sound2: "Diego.muda"
                })
            }
        }
        
        this.timeStop({
            duration: 5,
            cooldown_reply: 0.3,
            mental: {
                value: 1,
                interval: Math.floor(Mathf.random(30,40))
            }
        })
        
        
        
    }
    
    timeStop(data) {
        let player = this.standMaster;
        
        this.slot_data[1].var = [
            (this.use_skill2 && player?.isSneaking) || player?.hasTag("theWorld.timeStop"),
            (this.stop_tick.var / 20).toFixed(1),
            data.duration,
            NaN
        ].join("|")
        
        let gamerule = (boolean) => {
            let list = [
                "dodaylightcycle",
                "doweathercycle",
                "naturalregeneration",
                "dofiretick"
                // "tntexplodes"
            ]
            list.forEach(value => {
                this.runCommand(`gamerule ${value} ${boolean}`, player)
            })
        }
        let start_timer = 45;
        if (!player?.hasTag("tw.timestop_cooldown") && player?.hasTag("theWorld.timeStop") && this.mental_value.var > 0 && this.stop_tick.var > 0 && this.stop_tick.var <= data.duration * 20 && this.stop_tick2.var >= start_timer) {
            this.stop_tick.var -= 1;
        }
        if (player?.hasTag("tw.timestop_cooldown") && this.mental_value.var > 0 && this.stop_tick.var >= 0 && this.stop_tick.var < data.duration * 20) {
            this.stop_tick.var = Mathf.clamp(this.stop_tick.var + data.cooldown_reply, 0, data.duration * 20);
            if (this.stop_tick.var < data.duration * 20) {
                player?.removeTag("theWorld.timeStop")
            }
        }
        if (this.stop_tick.var >= data.duration * 20) {
            player?.removeTag("tw.timestop_cooldown")
        }
        if (!player?.hasTag("tw.timestop_cooldown") && player?.hasTag("theWorld.timeStop") && this.stop_tick.var > 0) {
            player?.removeTag("entity.in_timeStop")
            // this.runCommand(`effect @s weakness 0 0 true`, player)
            this.stop_tick2.var += 1;
            if (this.stop_tick2.var == 2) {
                this.MentalPanelUI();
                this.LoadingUI2(this.UI.theWorld.timeStop[this.timeStopColor.var]);
                // this.runCommand(`camerashake add @s 1 5`, player)
                if (this.shealth.var <= 30) {
                    this.runCommand(`playsound Diego.theWorld.timeStop2 @a ~ ~ ~`, player);
                } else {
                    this.runCommand(`playsound Diego.theWorld.timeStop @a ~ ~ ~`, player);
                }
                let lc = player.getViewDirection();
                let pos = "xyz".split("").map(xyz => {
                    return player.location[xyz] + (xyz === "y") + lc[xyz] * 2
                })
                this.broadcastAnim("the_world->time_stop");
                player?.addEffect("speed",start_timer - 6,{
                    amplifier: 6,
                    showParticles: false
                });
            }
            if (this.stop_tick2.var > 0) {
                gamerule(false)
                this.runCommand(`tag @e[tag=!theWorld.timeStop,tag=!entity.in_timeStop,r=64] add entity.in_timeStop`, player)
            }
            if (this.stop_tick2.var === start_timer) {
                // this.runCommand(`camerashake stop @s`, player)
            }
            if (this.stop_tick2.var > start_timer) {
                // this.runCommand(`gamerule randomtickspeed 4096`, player)
                this.runCommand(`gamerule randomtickspeed 1`, player)
                this.itemUseEvent.var = false;
                player?.removeTag("theWorld.stop_barrage_attack")
                this.MentalPanelUI();
                this.runCommand(`stopsound @a[tag=!theWorld.timeStop,r=64]`, player)
                this.LoadingUI2(this.UI.theWorld.greyScreen)
                if (this.stop_tick2.var % data.mental.interval == 0) {
                    this.removeMentalValue(data.mental.value);
                }
            } else {
                player?.addTag("remove.timeErase");
                player?.addTag("theWorld.stop_barrage_attack")
                this.itemUseEvent.var = true;

                let position = Object.fromEntries("xyz".split("").map(xyz => {
                    return [ xyz, player?.location[xyz] ]
                }));
                player?.teleport(position, {
                    rotation: {
                        x: player?.getRotation().x,
                        y: player?.getRotation().y
                    }
                })
            }
        }
        if ((!player?.hasTag("theWorld.timeStop")) || (player?.hasTag("theWorld.timeStop") && this.stop_tick.var <= 0)) {
            player?.removeTag("theWorld.stop_barrage_attack")
            if (!player?.hasTag("tw.timestop_cooldown") && this.stop_tick2.var > 0) {
                this.runCommand(`playsound Diego.theWorld.timeFlow @a ~ ~ ~`, player);
                this.LoadingUI2(this.UI.theWorld.timeFlow)
                this.stop_tick2.var = 1;
                this.itemUseEvent.var = true;
                this.runCommand(`gamerule randomtickspeed 1`, player)
                player?.addTag("tw.timestop_cooldown");
                // console.error(this.stop_tick2.var)
                // console.error(player?.hasTag("tw.timestop_cooldown"))
            }
            if (player?.hasTag("tw.timestop_cooldown") && this.stop_tick2.var > -1) {
                this.stop_tick2.var += 1;
                
                if (this.stop_tick2.var > 20) {
                    gamerule(true);
                    this.itemUseEvent.var = false;
                    this.LoadingUI2(this.UI.empty);
                    this.runCommand(`tag @e[tag=entity.in_timeStop] add remove.timeStop`, player)
                    
                    player?.removeTag("theWorld.timeStop");
                    this.stop_tick2.var = -1;
                }
            }
        }
    }
    
    quickMove(data) {
        let player = this.standMaster;
        
        this.slot_data[2].var = [
            this.use_skill2 && !player?.isSneaking,
            (this.move_cd.var / 20).toFixed(1),
            data.cooldown,
            NaN
        ].join("|")
        
        if (this.mental_value.var > 0 && this.move_cd.var >= 0 && this.move_cd.var < data.cooldown * 20) {
            this.move_cd.var += 1;
        }
        if (player?.hasTag("theWorld.quickMove") && this.move_cd.var >= data.cooldown * 20 && this.mental_value.var > 0) {
            let block = this.getBlockFromViewVector(player, data.range + 3, {liquid: false, passable: true});
            if (!player?.hasTag("theWorld.timeStop") && block !== undefined && block !== null) {
                let playerPos = "xyz".split("").map(xyz => {
                    return player?.location[xyz]
                })
                let blockPos = "xyz".split("").map(xyz => {
                    return block?.location[xyz]
                })
                let distance = new Vec3(...playerPos).Distance(...blockPos);
                let tpPos = Object.fromEntries("xyz".split("").map(xyz => {
                    return [ xyz, player?.location[xyz] + (xyz === "y") * 2 + this.getLc(player)[xyz] * distance ]
                }))
                player?.teleport(tpPos, {
                    rotation: {
                        x: player?.getRotation().x,
                        y: player?.getRotation().y
                    }
                })
                
                this.runCommand(`playsound theWorld.quickMove @a ~ ~ ~`, player);
    
                this.removeMentalValue(data.mental);
                this.move_cd.var = 0;
            }
            player?.removeTag("theWorld.quickMove");
        } else if (player?.hasTag("theWorld.quickMove") && this.move_cd.var < data.cooldown * 20) {
            player?.removeTag("theWorld.quickMove");
        }
    }
    
    static description(player,system) {
        let _this = system;
        let menu = _this.ui();
        menu.layout(player, `
            <ui id="_stand_description_"/>
                <title text="ui.stand_settings.skills_description"/>
                    <body text="ui.how_to_use.no_stand"/>
                        <button id="skill1" text="ui.stand_settings.3.how_to_use.stand_fist" icon="textures/gui/theWorld/icon1"/>
                        <button id="skill2" text="ui.stand_settings.3.how_to_use.theWorld_timeStop" icon="textures/gui/theWorld/icon2"/>
                        <button id="skill3" text="ui.stand_settings.3.how_to_use.theWorld_quickMove" icon="textures/gui/theWorld/icon3"/>
                        <button id="close" text="ui.stand_settings.3"/>
                    </body>
                </title>
            </ui>
        `
        );
        menu.trigger("_stand_description_", e => {
            let canceled = e.canceled;
            _this.ui_using(player,0);
            
            let selection = e.getElementById;
            _this.menu_op(player);
        });
    }
    
    static eventData(_this) {
        let c = (entity) => {
            return entity !== undefined && entity?.typeId == "minecraft:player" && entity?.hasTag("standMaster.theWorld")
        }
        _this.listenForEvent("minecraft:beforeItemUse", (eventData) => {
            let boolean = _this.GlobalVar(mc.world,"itemUseEvent");
            eventData.cancel = boolean.var
        })
        _this.listenForEvent("minecraft:beforeItemUseOn", (eventData) => {
            let boolean = _this.GlobalVar(mc.world,"itemUseEvent");
            eventData.cancel = boolean.var
        })
        _this.listenForEvent("minecraft:itemStartUse", (eventData) => {
            let { itemStack, source } = eventData;
            if (c(source) && itemStack?.typeId === "stand:skill2") {
                if (!source?.isSneaking) {
                    source?.addTag("theWorld.quickMove");
                } else/* if (!source?.hasTag("entity.in_timeErase"))*/ {
                    let setTag = [
                        "removeTag",
                        "addTag"
                    ]
                    let tag = "theWorld.timeStop";
                    source[setTag[+!source?.hasTag(tag)]](tag);
                }
            }
        })
        _this.tick(() => {
            _this.getEntities({excludeTypes:["minecraft:xp_orb"],excludeTags:["theWorld.timeStop"],tags:["entity.in_timeStop"]})/*.filter(e => e?.getVelocity().x !== 0 && e?.getVelocity().y !== 0 && e?.getVelocity().z !== 0)*/.forEach(entity => {
                if (!entity?.hasTag("remove.timeStop")) {
                    if (!entity?.hasTag("saveVector")) {
                        let overlayPosition = Object.fromEntries("xyz".split("").map(xyz => {
                            return [ xyz, {var: entity?.location[xyz] * 100} ]
                        }))
                        "xyz".split("").map(xyz => {
                            try {
                                overlayPosition[xyz] = _this.scores(entity,"overlayPosition" + xyz.toUpperCase());
                            } catch(e) {
                                overlayPosition[xyz] = {
                                    var: entity?.location[xyz] * 100
                                }
                            }
                            overlayPosition[xyz].var = entity?.location[xyz].toFixed(2) * 100
                        })
                        let overlayVelocity = Object.fromEntries("xyz".split("").map(xyz => {
                            return [ xyz, {var:0} ]
                        }))
                        "xyz".split("").map(xyz => {
                            try {
                                overlayVelocity[xyz] = _this.scores(entity,"overlayVelocity" + xyz.toUpperCase());
                            } catch(e) {
                                overlayVelocity[xyz] = {
                                    var: 0
                                }
                            }
                            overlayVelocity[xyz].var = entity?.getVelocity()[xyz].toFixed(2) * 100
                        })
                        let overlayRotation = Object.fromEntries("xy".split("").map(xy => {
                            return [ xy, {var:0} ]
                        }))
                        "xy".split("").map(xy => {
                            try {
                                overlayRotation[xy] = _this.scores(entity,"overlayRotation" + xy.toUpperCase());
                            } catch(e) {
                                overlayRotation[xy] = {
                                    var: 0
                                }
                            }
                            overlayRotation[xy].var = entity?.getRotation()[xy].toFixed(2) * 100
                        })
                        if (entity?.typeId !== "minecraft:player") {
                            entity?.clearVelocity();
                        }
                        entity.addTag(`saveVector`)
                    } else {
                        let overlayPosition = Object.fromEntries("xyz".split("").map(xyz => {
                            return [ xyz, {var: entity?.location[xyz] * 100} ]
                        }))
                        let position = Object.fromEntries("xyz".split("").map(xyz => {
                            try {
                                overlayPosition[xyz] = _this.scores(entity,"overlayPosition" + xyz.toUpperCase());
                            } catch(e) {
                                overlayPosition[xyz] = {
                                    var: entity?.location[xyz] * 100
                                }
                            }
                            return [ xyz, overlayPosition[xyz].var / 100 ]
                        }))
                        let overlayVelocity = Object.fromEntries("xyz".split("").map(xyz => {
                            return [ xyz, {var:0} ]
                        }))
                        let velocity = "xyz".split("").map(xyz => {
                            try {
                                overlayVelocity[xyz] = _this.scores(entity,"overlayVelocity" + xyz.toUpperCase());
                            } catch(e) {
                                overlayVelocity[xyz] = {
                                    var: 0
                                }
                            }
                            return overlayVelocity[xyz].var / 100
                        })
                        let overlayRotation = Object.fromEntries("xy".split("").map(xy => {
                            return [ xy, {var:0} ]
                        }))
                        let rotation = Object.fromEntries("xy".split("").map(xy => {
                            try {
                                overlayRotation[xy] = _this.scores(entity,"overlayRotation" + xy.toUpperCase());
                            } catch(e) {
                                overlayRotation[xy] = {
                                    var: 0
                                }
                            }
                            return [ xy, overlayRotation[xy].var / 100 ]
                        }))
                        let position2 = Object.fromEntries("xyz".split("").map(xyz => {
                            return [ xyz, entity?.location[xyz] + (xyz === "y") * ((entity?.typeId === "minecraft:item" ? 0.04 : 0) + (entity?.typeId === "minecraft:tnt" ? 0.04 : 0)) ]
                        }));
                        let positionFacing = Object.fromEntries("xyz".split("").map((xyz,index) => {
                            return [ xyz, entity?.location[xyz] + velocity[index] /*+ (xyz === "x" || xyz === "z") * -1*/ + (xyz === "y") * ((entity?.typeId === "minecraft:item" ? 0.04 : 0) + (entity?.typeId === "minecraft:falling_block" ? 0.4 : 0)) ]
                        }));
                        let velocity2 = velocity.map(xyz => {
                            return xyz / Math.pow(10,10)
                        })
                        
                        entity?.addEffect("weakness", 9999 * 20, {
                            amplifier: 255,
                            showParticles: false
                        });

                        
                        if (entity?.typeId === "minecraft:player" && !entity?.hasTag("standMaster.theWorld")) {
                            _this.runCommand(`camera @s fade time 0 0.2 0.1 color 0 0 0`, entity)
                        }
                        if (entity?.typeId !== "minecraft:player") {
                            entity?.clearVelocity();
                        }
                        if (entity?.hasComponent("minecraft:movement")) {
                            entity?.teleport(position, {
                                rotation: rotation,
                                keepVelocity: entity?.typeId !== "minecraft:player"
                            })
                        } else {
                            entity?.applyImpulse(new Vec3(...velocity2).Vector());
                            entity?.teleport(position2, {
                                keepVelocity: entity?.typeId !== "minecraft:tnt"
                            })
                        }
                        
                    }
                } else {
                    entity?.removeTag("saveVector");
                    /*
                    if (entity?.typeId === "minecraft:player") {
                        let player = entity;
                        let customUI = new titleUI(player);
                        let LoadingUI2 = (ui) => {
                            return customUI.loadingUI2(ui);
                        }
                        let UI = titleUIList.ui;
                        LoadingUI2(UI.empty)
                    }
                    */
                    _this.runCommand(`effect @s weakness 0 0 true`, entity)
                    let overlayVelocity = Object.fromEntries("xyz".split("").map(xyz => {
                        return [ xyz, {var:0} ]
                    }))
                    let overlayKnockback = Object.fromEntries("xzvh".split("").map(xzvh => {
                        return [ xzvh, {var:0} ]
                    }))
                    if (entity?.typeId !== "minecraft:player") {
                        let velocity = "xyz".split("").map(xyz => {
                            try {
                                overlayVelocity[xyz] = _this.scores(entity,"overlayVelocity" + xyz.toUpperCase());
                            } catch(e) {
                                overlayVelocity[xyz] = {
                                    var: 0
                                }
                            }
                            return overlayVelocity[xyz].var / 100
                        })
                        entity?.applyImpulse(new Vec3(...velocity).Vector());
                    } else {
                        let knockback = "xzvh".split("").map(xzvh => {
                            try {
                                overlayKnockback[xzvh] = system.scores(entity,"overlayKnockback" + xzvh.toUpperCase());
                            } catch(e) {
                                overlayKnockback[xzvh] = {
                                    var: 0
                                }
                            }
                            return overlayKnockback[xzvh].var / 100
                        })
                        entity?.applyKnockback(...knockback);
                    }
                    if (entity?.hasTag("overlayDamage")) {
                        let overlayDamage = {
                            var: 0
                        }
                        try {
                            overlayDamage = _this.scores(entity,"overlayDamage");
                        } catch(e) {
                            overlayDamage = {
                                var: 0
                            }
                        }
                        let damage2 = overlayDamage.var - (entity?.typeId === "minecraft:player") * 2;
                        
                        if (entity?.typeId === "minecraft:player" && entity?.getTags().join("|").includes("standMaster.") && !entity?.hasTag("gameMode.creative")) {
                            let health = entity?.getComponent("minecraft:health");
                            let shealth = _this.GlobalVar(entity,"standMaster.health");
                            let shealth_max = _this.GlobalVar(entity,"standMaster.health_max");
                            if (shealth.var >= 0) {
                                shealth.var = Mathf.clamp(shealth.var - damage2, 0, shealth_max.var);
                                _this.runCommand(`damage @s[type=!ender_dragon] 0 suicide`, entity)
                            } else {
                                _this.runCommand(`damage @s[type=!ender_dragon] ${damage2} suicide`, entity)
                            }
                        } else {
                            let command1a = `damage @s[type=!ender_dragon] ${damage2} entity_attack`;
                            let command1b = `damage @s[type=!ender_dragon] ${damage2} entity_attack entity @a`;
                            let command2 = `damage @s[type=ender_dragon] ${damage2} suicide entity @a`;
                            let command3 = `effect @s[type=!player] slowness 1 10 true`;
                            _this.runCommands([
                                command1a,
                                command2,
                                command3
                            ], entity);
                        }
                        overlayDamage.var = 0;
                        entity?.removeTag("overlayDamage");
                        entity?.removeTag("isAttackedByFist");
                        entity?.removeTag("isHitByFist");
                    }
                    "xyz".split("").map(xyz => {
                        overlayVelocity[xyz].var = 0;
                    })
                    "xzvh".split("").map(xzvh => {
                        overlayKnockback[xzvh].var = 0;
                    })
                    entity?.removeTag("remove.timeStop")
                    entity?.removeTag("entity.in_timeStop")
                }
            })
        },1);
        _this.listenForEvent("minecraft:itemStartUse", (eventData) => {
            let entity = eventData.source;
            let item = eventData.itemStack;
            if (c(entity)) {
                let player = entity;
                let inventory = player?.getComponent("inventory").container;
                if (item.typeId == "jojo:stand_settings" && player?.isSneaking) {
                    
                    let menu = _this.ui();
                    menu.layout(player, `
                        <ui id="_effect_choice_"/>
                            <title text="ui.stand_settings.option_slot"/>
                                <body text="ui.stand_settings.the_world"/>
                                    <button id="white" text="ui.stand_settings.3.stand.slot.1" icon="textures/effect/timeStopWhite"/>
                                    <button id="black" text="ui.stand_settings.3.stand.slot.2" icon="textures/effect/timeStopBlack"/>
                                    <button id="null1" text="ui.stand_settings.3.stand.slot.3" icon="null"/>
                                    <button id="null2" text="ui.stand_settings.3.stand.slot.4" icon="null"/>
                                    <button id="null3" text="ui.stand_settings.3.stand.slot.5" icon="null"/>
                                    <button id="null4" text="ui.stand_settings.3.stand.slot.6" icon="null"/>
                                    <button id="null5" text="ui.stand_settings.3.stand.slot.7" icon="null"/>
                                    <button id="null6" text="ui.stand_settings.3.stand.slot.8" icon="null"/>
                                    <button id="close" text="ui.stand_settings.3" icon="null"/>
                                </body>
                            </title>
                        </ui>
                    `
                    );
                    menu.trigger("_effect_choice_", e => {
                        let selection = e.getElementById;
                        let text = {
                            rawtext: [
                                {
                                    translate: `chat.theWorld.timeStopEffect.is_selected`
                                },
                                {
                                    translate: `color.${selection}`
                                }
                            ]
                        };
                        if (selection === "white" || selection === "black") {
                            _this.GlobalVar(player,"timeStopColor").var = selection;
                            player?.sendMessage(text);
                        }
                        
                    });
                }
            }
        })
    }
    
}

