export default function antiCheat(globalData: IGlobalData) {

    const allowedWeaponHashes: number[] = [
        453432689,
        3219281620,
        1593441988,
        2578377531,
        736523883,
        171789620,
        3220176749,
        487013001,
        2210333304,
        1649403952,
        100416529,
        2725352035,
        2508868239,
        2343591895,
        3638508604,
        1737195953,
        -270015777,
        911657153,
        -1716589765,
        -2084633992,
        -1075685676,
        -1786099057,
        -1074790547,
        -1569615261
    ]

    mp.events.add("playerJoin", () => {
        mp.events.call("client:respawning")
    });

    mp.events.add("client:checkInvincible", () => {
        //if (mp.players.local.dimension == 0) return
        if (!Behaviour.active) return
        var healthBefore = Behaviour.health
        mp.players.local.applyDamageTo(1, true);
        setTimeout(() => {
            if (healthBefore == Behaviour.health) {
                if (mp.players.local.getHealth() > 0) {
                    mp.events.callRemote('CLIENT:CheatDetection', "Static Godmode")
                }
            }
            else {
                Behaviour.sleep(1)
                mp.players.local.setHealth(healthBefore + 100)
            }
        }, 500);
    })

    //setInterval(() => {
    //    mp.events.call("client:checkInvincible")
    //}, 30000);

    mp.events.add('SERVER:AntiCheat:weaponSwap', () => {
        Behaviour.resetWeapon()
    })

    mp.events.add('playerWeaponShot', () => {
        if (Behaviour.checkWeaponhash()) {
            mp.events.callRemote("CLIENT:CheatDetection", "Unallowed Weapon", Behaviour.weapon)
        }
        if (Behaviour.reloadingWeapon) {
            //mp.events.callRemote("CLIENT:CheatDetection", "No Reload")
            Behaviour.resetWeapon()
        }
        Behaviour.updateMagSize()
    });

    mp.keys.bind(0x52, true, () => {
        Behaviour.reloading = true
        setTimeout(() => {
            Behaviour.magazin = mp.game.weapon.getWeaponClipSize(mp.game.invoke(`0x0A6DB4965674D243`, mp.players.local.handle))
            Behaviour.reloading = false
        }, 2000);
    })

    mp.events.add('client:respawning', () => {
        if (Behaviour.active) Behaviour.sleep(3)
    })

    class PlayerBehaviour {
        active: boolean;
        flags: number;
        hits: number;
        reloadingWeapon: boolean;
        pos: Vector3Mp;
        health: number;
        weapon: number;
        magazin: number;
        firstshot: boolean;
        reloading: boolean;
        range_to_btm: number;

        constructor() {
            this.active = true
            this.flags, this.hits = 0
            this.reloadingWeapon = false
            this.pos = mp.players.local.position
            this.health = Number(mp.players.local.getHealth()) + Number(mp.players.local.getArmour())
            this.weapon = Number(mp.game.invoke(`0x0A6DB4965674D243`, mp.players.local.handle));
            this.magazin = mp.game.weapon.getWeaponClipSize(this.weapon)
            this.firstshot = true
        }
        sleep(duration) {
            this.active = false
            setTimeout(() => {
                this.active = true
            }, duration * 1000);
        }
        secs() {
            return Math.round(Date.now() / 1000)
        }

        isRagdollOnHeight(height) {
            this.range_to_btm = mp.game.gameplay.getGroundZFor3dCoord(mp.players.local.position.x, mp.players.local.position.y, mp.players.local.position.z, 0, false);
            if (Math.abs(mp.players.local.position.z - this.range_to_btm) > Math.abs(height - this.range_to_btm)) {
                if (!this.isWalking()) {
                    return false;
                } else if (this.active && this.range_to_btm > 0) {
                    return true;
                }
                return false
            }
        }
        isWalking() {
            if (mp.players.local.isFalling() || mp.players.local.isRagdoll()) return false
            else if (!mp.players.local.vehicle) return true
        }
        subtractVector(v1, v2) {
            return { "x": v1.x - v2.x, "y": v1.y - v2.y, "z": v1.z - v2.z }
        }
        VehicleFasterThan(max) {
            if (mp.players.local.vehicle) {
                if (mp.players.local.vehicle.getClass() != 16) {
                    return mp.players.local.vehicle.getSpeed() * 3.6 > max
                }
            }
            return false
        }
        checkCarPos(maxHeight = 50) {
            if (mp.players.local.vehicle) {
                if (mp.players.local.vehicle.getClass() != 15 && mp.players.local.vehicle.getClass() != 16) {
                    this.range_to_btm = mp.game.gameplay.getGroundZFor3dCoord(mp.players.local.position.x, mp.players.local.position.y, mp.players.local.position.z, 0, false);
                    if (mp.players.local.position.z - this.range_to_btm > maxHeight + this.range_to_btm) {
                        return true
                    }
                    return false
                }
            }
        }
        checkWeaponhash() {
            let h = this.weapon;
            if (allowedWeaponHashes.indexOf(h) === -1) {
                return true
            }
            return false
        }
        resetWeapon() {
            this.weapon = mp.game.invoke(`0x0A6DB4965674D243`, mp.players.local.handle)
            this.magazin = mp.game.weapon.getWeaponClipSize(this.weapon)
            this.reloadingWeapon = false
        }
        updateMagSize() {
            this.weapon = mp.game.invoke(`0x0A6DB4965674D243`, mp.players.local.handle)
            if (this.firstshot) {
                this.firstshot = false
                this.resetWeapon()
            }
            this.magazin -= 1
            if (this.magazin <= 0) {
                this.reloadingWeapon = true
                setTimeout(() => {
                    this.reloadingWeapon = false
                    this.resetWeapon()
                }, 1250);
            }
        }
    }

    var Behaviour = new PlayerBehaviour()
    var loop = Behaviour.secs()

    function isUsingController() {
        return !mp.game.controls.isInputDisabled(0);
    }

    mp.events.add("render", () => {
        mp.game.player.setHealthRechargeMultiplier(0);

        if (isUsingController()) {
            mp.game.controls.disableControlAction(32, 24, true);
            mp.game.controls.disableControlAction(32, 25, true);

            mp.game.controls.disableControlAction(32, 91, true);
            mp.game.controls.disableControlAction(32, 92, true);

            mp.game.controls.disableControlAction(32, 69, true);
            mp.game.controls.disableControlAction(32, 70, true);
        }

        Behaviour.health = Number(mp.players.local.getHealth()) + Number(mp.players.local.getArmour())
        if (loop < Behaviour.secs()) {
            if (Behaviour.active) {
                let Difference = Behaviour.subtractVector(Behaviour.pos, mp.players.local.position)
                if (Math.abs(Difference.x) > 30 || Math.abs(Difference.y) > 30) {
                    if (Behaviour.isWalking()) {
                        //mp.events.callRemote("CLIENT:CheatDetection", "Flyhack/Teleport")
                    }
                }
                if (mp.players.local.vehicle) {
                    if (Behaviour.checkCarPos(25)) {
                        //mp.events.callRemote("CLIENT:CheatDetection", "Vehicle Flyhack")
                    }
                    if (Behaviour.VehicleFasterThan(250)) {
                        mp.events.callRemote("CLIENT:CheatDetection", "Vehicle Speedhack")
                    }
                }
            }
            Behaviour.pos = mp.players.local.position
            loop = Behaviour.secs() + 3;
        }
    });

    setInterval(() => {
        let hp = Behaviour.health
        setTimeout(() => {
            if (hp < Behaviour.health && Behaviour.active) {
                mp.events.callRemote("CLIENT:CheatDetection", "Healkey (unexpected HP added)")
            }
        }, 400);
    }, 500);
}