import { debug } from "util";

export default function animationSync() {
    let blockInput = false;
    let animationBreakTimer;

    mp.events.add("SERVER:LoadAnimations", () => {
        animationSyncData.register("Cuffed", "mp_arresting", "idle", -1, true, 50, false);
        animationSyncData.register("doArrest", "mp_arrest_paired", "cop_p2_back_right", 3760, false, 0, false);
        animationSyncData.register("getArrest", "mp_arrest_paired", "crook_p2_back_right", 3760, false, 0, false);
        animationSyncData.register("doUncuff", "mp_arresting", "a_uncuff", 5500, false, 0, false);
        animationSyncData.register("getUncuff", "mp_arresting", "b_uncuff", 5500, false, 0, false);
        animationSyncData.register("hup", "mp_am_hold_up", "handsup_base", -1, true, 50, true);
        animationSyncData.register("carryBox", "anim@heists@box_carry@", "idle", -1, true, 50, true);
    });

    const animationBreakMessage = [
        { animName: "Cuffed", msg: "Handschellen gebrochen." }
    ];

    const animationSyncData =
    {
        animations: [],

        register: function (name, animDict, animName, duration, loop, flag, endless) {
            let id = mp.game.joaat(name);

            if (!this.animations.hasOwnProperty(id)) {
                this.animations[id] =
                {
                    id: id,
                    name: name,
                    animDict: animDict,
                    animName: animName,
                    duration: duration,
                    loop: loop,
                    flag: flag,
                    endless: endless
                };
            } else {
                mp.game.graphics.notify("Animation Sync Error: ~r~Duplicate Entry");
            }
        }
    };

    /*
    mp.events.add("entityStreamIn", (entity) => {
        if (entity.type === "player" && entity.animationData) {
            if (!entity.animationData.playOnStream)
                return;
            animationSync.playAnim(entity, mp.game.joaat(entity.animationData.name));
        }
    });
    */

    setInterval(() => {
        if (mp.players.local.getVariable("AnimationData")) {
            let index = mp.game.joaat(mp.players.local.getVariable("AnimationData"));
            let currentAnim = animationSyncData.animations[index];
            let { id, name, animDict, animName, duration, loop, flag } = currentAnim;
            if (loop) {
                blockInput = true;
            } else {
                blockInput = false;
            }
        }

        mp.players.forEachInStreamRange(
            (player) => {
                if (!player.getVariable("AnimationData")) {
                    return;
                }

                let index = mp.game.joaat(player.getVariable("AnimationData"));

                let currentAnim = animationSyncData.animations[index];
                let { id, name, animDict, animName, duration, loop, flag } = currentAnim;

                if (loop == true && !player.isPlayingAnim(animDict, animName, 3)) {
                    loadAnimDict(animDict, function () {
                        mp.players.exists(player) && 0 !== player.handle && player.taskPlayAnim(animDict, animName, 1, 0, duration, parseInt(flag), 0, !1, !1, !1)
                    });
                }
            });
    }, 100);

    mp.events.addDataHandler("AnimationData", (entity, string) => {
        entity.clearTasksImmediately();
        if (animationBreakTimer) {
            clearTimeout(animationBreakTimer);
            animationBreakTimer = null;
        }
        if (string == null) {
            blockInput = false;
            return;
        }

        let index = mp.game.joaat(string);

        if (!animationSyncData.animations.hasOwnProperty(index)) return;

        let animData = animationSyncData.animations[index];

        let { id, name, animDict, animName, duration, loop, flag, endless } = animData;

        loadAnimDict(animDict, function () {
            mp.players.exists(entity) && 0 !== entity.handle && entity.taskPlayAnim(animDict, animName, 1, 0, duration, parseInt(flag), 0, !1, !1, !1)
        });

        if (mp.players.local == entity) {
            if (!endless) {
                animationBreakTimer = setTimeout(() => breakAnimation(name), 120000);
            }

            if (!loop) {
                let a = setTimeout(function () {
                    clearTimeout(a);
                    mp.events.callRemote("CLIENT:ClearAnimationData", true);
                }, duration);
            }
        }
    });

    function breakAnimation(name) {
        let { animName, msg } = animationBreakMessage.find(c => c.animName == name)

        if (msg)
            mp.events.call("BN_Show", msg);

        clearInterval(animationBreakTimer);
        animationBreakTimer = null;
        mp.events.callRemote("CLIENT:ClearAnimationData", false);
    }

    const blockInputControls = [12, 13, 14, 15, 22, 24, 25, 37, 261, 262];

    mp.events.add("render", () => {
        if (blockInput) {
            blockInputControls.forEach((ctrl) => {
                mp.game.controls.disableControlAction(32, ctrl, true);
            });
        }
    });

    function loadAnimDict(animDict, callback) {
        if (mp.game.streaming.hasAnimDictLoaded(animDict)) return void callback();
        mp.game.streaming.requestAnimDict(animDict);
        let c = setInterval(function () {
            mp.game.streaming.hasAnimDictLoaded(animDict) && (clearInterval(c), callback())
        }, 100)
    }

    mp.events.add("SERVER:SetInFrontPosition", (entity) => {
        mp.events.callRemote("CLIENT:SET_InFrontOfPos", entity.getOffsetFromInWorldCoords(0, 1, 0));
    });
}