import { world, Player, system, GameMode } from '@minecraft/server';
import { Command } from '../handler';
import { sendPlayerMessage, config, sendAllMessage } from '../../config';
import { lifesteal, getPlayer, getScore, setScore, addScore } from '../../lifesteal';

export function heartHelp(player: Player) {
    if (player.hasTag(config.staffTag) || player.isOp()) {
        sendPlayerMessage(player, `§e§lLifesteal Help Page -- Heart§r§6
> Withdraw a certain amount of hearts into your inventory

> Usage: ${config.prefix}heart <display/show/set/reset/setmax>

> Args: [
    display - Display your max health above your head, anyone can see it
    show - Display your max health to yourself through an actionbar
    set - Set a player's max health
    setmax - Set the maximum amount of hearts a player can get
    envsteal - Toggle whether or not you lose hearts from natural damage (such as fall damage and mobs)
    add - Adds hearts to a player's max heart count
    remove - Remove hearts from a player's max heart count
    get - See how many hearts a player has
    gain - Set the amount of hearts gained when killing a player
    lose - Set the amount of hearts lost when getting killed
    count - Tells you how many hearts you have
    notify - Toggles whether you get notified when losing a heart or not
]

> Examples: [
    ${config.prefix}heart display
    ${config.prefix}heart show
    ${config.prefix}heart notify
    ${config.prefix}heart count
    ${config.prefix}heart reset ${player.name}
    ${config.prefix}heart set ${player.name} 16
    ${config.prefix}heart setmax 30
    ${config.prefix}heart envsteal true
    ${config.prefix}heart envsteal false
    ${config.prefix}heart add 5 ${player.name}
    ${config.prefix}heart remove 5 ${player.name}
    ${config.prefix}heart get ${player.name}
    ${config.prefix}heart gain 3
    ${config.prefix}heart lose 2
]`);
        return;
    }
    sendPlayerMessage(player, `§e§lLifesteal Help Page -- Heart§r§6
> Withdraw a certain amount of hearts into your inventory

> Usage: ${config.prefix}heart <display/show/set/setmax>

> Args: [
    display - Display your max health above your head
    show - Display your max health to only yourself
    notify - Toggles whether you get notified when losing a heart or not
]

> Examples: [
    ${config.prefix}heart display
    ${config.prefix}heart display
    ${config.prefix}heart show
    ${config.prefix}heart show
    ${config.prefix}heart notify
]`);
}

function staffCheck(player: Player, message: string) {
    if (!player.hasTag(config.staffTag) && !player.isOp()) {
        sendPlayerMessage(player, message);
        return true;
    }
}

new Command({
    name: 'heart',
    code({ player, args }) {
        if (!args[0]) return heartHelp(player);

        switch (args.shift()) {
            case `notify`:
                function heartNotify() {
                    if (player.hasTag(`ls-dead`)) return sendPlayerMessage(player, `§8[§cX§8] §cYou are a ghost and do not have permission to use this!`);
                    if (player.hasTag(`heart-notify-off`)) {
                        sendPlayerMessage(player, `§8[§a/§8] §aTurned heart notifications on`);
                        return player.removeTag(`heart-notify-off`);
                    }
                    sendPlayerMessage(player, `§8[§a/§8] §aTurned heart notifications off`);
                    player.addTag(`heart-notify-off`);
                }
                heartNotify();
                break;
            case `count`:
                function heartCount() {
                    sendPlayerMessage(player, `§aYou have §f${getScore(player, `ls-death`)}§a hearts`);
                }
                heartCount();
                break;
            case `display`:
                function heartDisplay() {
                    if (player.hasTag(`ls-dead`)) return sendPlayerMessage(player, `§8[§cX§8] §cYou are a ghost and do not have permission to use this!`);
                    if (player.hasTag(`heart-display_on`)) {
                        sendPlayerMessage(player, `§8[§a/§8] §aTurned heart display off`);
                        return player.removeTag(`heart-display_on`);
                    }
                    sendPlayerMessage(player, `§8[§a/§8] §aTurned heart display on`);
                    player.addTag(`heart-display_on`);
                }
                heartDisplay();
                break;
            case `show`:
                function heartShow() {
                    if (player.hasTag(`ls-dead`)) return sendPlayerMessage(player, `§8[§cX§8] §cYou are a ghost and do not have permission to use this!`);
                    if (player.hasTag(`heart-show_on`)) {
                        sendPlayerMessage(player, `§8[§a/§8] §aTurned heart show off`);
                        return player.removeTag(`heart-show_on`);
                    }
                    sendPlayerMessage(player, `§8[§a/§8] §aTurned heart show on`);
                    player.addTag(`heart-show_on`);
                }
                heartShow();
                break;
            case `set`:
                if (staffCheck(player, `§8[§cX§8] §cYou are not allowed to use this command!`)) return;
                function heartSet() {
                    let msg = isNaN(+args[1]) ? args.slice(0).join(` `).split(/\"/g)[1] : args[0];
                    let target = getPlayer(msg);

                    if (!target && args[0]?.replace(/\w*[^\d]\w*/g, ``).match(/\d+/) && !args[1]) {
                        let amount = +args[0];

                        setScore(player, `ls-death`, amount);
                        sendPlayerMessage(player, `§8[§a/§8] §aSet §f${player.name}§a's max hearts to §f${amount}`);
                        if (player.hasTag(`ls-dead`) && amount > 0) {
                            player.removeTag(`ls-dead`);
                            player.setGameMode(GameMode.survival);
                        }
                        return;
                    }

                    let amount = args[args.length - 1];
                    if (!target) return sendPlayerMessage(player, `§8[§cX§8] §cFailed to find player as they don't exist or aren't online (${msg}), make sure to surround a player's name with §f"§c if they have a space in their name`);
                    if (!amount || isNaN(+amount)) return sendPlayerMessage(player, `§8[§cX§8] §cAmount is invalid`);

                    setScore(target, `ls-death`, +amount);
                    sendPlayerMessage(player, `§8[§a/§8] §aSet §f${target.name}§a's max hearts to §f${amount}`);

                    if (target.hasTag(`ls-dead`) && +args[0] > 0) {
                        target.removeTag(`ls-dead`);
                        player.setGameMode(GameMode.survival);
                    }
                }
                heartSet();
                break;
            case `reset`:
                if (staffCheck(player, `§8[§cX§8] §cYou are not allowed to use this command!`)) return;
                let msg = args.slice(0).join(` `);
                let target = getPlayer(msg);
                let startamount = +lifesteal.get(`startamount`);

                if (!args[0]) {
                    setScore(player, `ls-death`, startamount);
                    sendPlayerMessage(player, `§8[§a/§8] §aReset §f${player.name}§a's max hearts to §f${startamount}`);
                    if (player.hasTag(`ls-dead`)) {
                        player.removeTag(`ls-dead`);
                        player.setGameMode(GameMode.survival);
                    }
                    return;
                }

                if (!target) return sendPlayerMessage(player, `§8[§cX§8] §cFailed to find player as they don't exist or aren't online (${msg}), make sure to surround a player's name with §f"§c if they have a space in their name`);

                setScore(target, `ls-death`, startamount);
                sendPlayerMessage(player, `§8[§a/§8] §aReset §f${target.name}§a's max hearts to §f${startamount}`);

                if (target.hasTag(`ls-dead`)) {
                    target.removeTag(`ls-dead`);
                    player.setGameMode(GameMode.survival);
                }
                break;
            case `setmax`:
                if (staffCheck(player, `§8[§cX§8] §cYou are not allowed to use this command!`)) return;
                function setMax() {
                    let amount = args[0];
                    if (!amount) return sendPlayerMessage(player, `§aMaximum hearts is set to §f${lifesteal.get(`maxhearts`)}`);
                    if (isNaN(+amount)) return sendPlayerMessage(player, `§8[§cX§8] §cAmount is invalid`);
                    if (+amount > 200 || +amount < 10) return sendPlayerMessage(player, `§8[§cX§8] §cYou can only set the max hearts from 10-200`);

                    lifesteal.set(`maxhearts`, amount);
                    sendPlayerMessage(player, `§8[§a/§8] §aSet the maximum amount of hearts players can get to §f${amount}`);
                }
                setMax();
                break;
            case `envsteal`:
                if (staffCheck(player, `§8[§cX§8] §cYou are not allowed to use this command!`)) return;
                function heartEnvsteal() {
                    if (!args[0]) return sendPlayerMessage(player, `§aEnvsteal is set to §f${lifesteal.get(`envsteal`)}`);

                    if (![`true`, `false`].includes(args[0].toLowerCase())) return sendPlayerMessage(player, `§8[§cX§8] §cMust be true or false`);
                    lifesteal.set(`envsteal`, args[0].toLowerCase());

                    sendPlayerMessage(player, `§8[§a/§8] §aSet environment steal to §f${args[0]}`);
                }
                heartEnvsteal();
                break;
            case `add`:
                if (staffCheck(player, `§8[§cX§8] §cYou are not allowed to use this command!`)) return;
                function heartAdd() {
                    let msg = isNaN(+args[1]) ? args.slice(0).join(` `).split(/\"/g)[1] : args[0];
                    let target = getPlayer(msg);

                    if (!target && args[0]?.replace(/\w*[^\d]\w*/g, ``).match(/\d+/) && !args[1]) {
                        let score = getScore(player, `ls-death`);
                        let amount = +args[0];

                        addScore(player, `ls-death`, +amount);
                        sendPlayerMessage(player, `§8[§a/§8] §aAdded §f${amount}§a to §f${player.name}§a's max heart count (Now §f${score + amount}§a)`);

                        if (player.hasTag(`ls-dead`) && amount > 0) {
                            player.removeTag(`ls-dead`);
                            player.setGameMode(GameMode.survival);
                        }
                        return;
                    }

                    let amount = +args[args.length - 1];
                    if (!target) return sendPlayerMessage(player, `§8[§cX§8] §cFailed to find player as they don't exist or aren't online (${msg}), make sure to surround a player's name with §f"§c if they have a space in their name`);
                    if (!amount || isNaN(amount)) return sendPlayerMessage(player, `§8[§cX§8] §cAmount is invalid`);

                    let score = getScore(target, `ls-death`);

                    addScore(target, `ls-death`, amount);
                    sendPlayerMessage(player, `§8[§a/§8] §aAdded §f${amount}§a to §f${target.name}§a's max heart count (Now §f${score + amount}§a)`);

                    if (target.hasTag(`ls-dead`) && +args[0] > 0) {
                        target.removeTag(`ls-dead`);
                        target.setGameMode(GameMode.survival);
                    }
                }
                heartAdd();
                break;
            case `remove`:
                if (staffCheck(player, `§8[§cX§8] §cYou are not allowed to use this command!`)) return;
                function heartRemove() {
                    let msg = isNaN(+args[1]) ? args.slice(0).join(` `).split(/\"/g)[1] : args[0];
                    let target = getPlayer(msg);

                    if (!target && args[0]?.replace(/\w*[^\d]\w*/g, ``).match(/\d+/) && !args[1]) {
                        let score = getScore(player, `ls-death`);
                        let amount = +args[0];

                        addScore(player, `ls-death`, -amount);
                        sendPlayerMessage(player, `§8[§a/§8] §aRemoved §f${amount}§a from §f${player.name}§a's max heart count (Now §f${score - amount}§a)`);
                        return;
                    }

                    let amount = +args[args.length - 1];
                    if (!target) return sendPlayerMessage(player, `§8[§cX§8] §cFailed to find player as they don't exist or aren't online (${msg}), make sure to surround a player's name with §f"§c if they have a space in their name`);
                    if (!amount || isNaN(amount)) return sendPlayerMessage(player, `§8[§cX§8] §cAmount is invalid`);

                    let score = getScore(target, `ls-death`);

                    addScore(target, `ls-death`, -amount);
                    sendPlayerMessage(player, `§8[§a/§8] §aRemoved §f${amount}§a from §f${target.name}§a's max heart count (Now §f${score - amount <= 0 ? score - amount : 0}§a)`);
                }
                heartRemove();
                break;
            case `get`:
                if (staffCheck(player, `§8[§cX§8] §cYou are not allowed to use this command!`)) return;
                function heartGet() {
                    let msg = isNaN(+args[1]) ? args.slice(0).join(` `).split(/\"/g)[0] : args[0];
                    let target = getPlayer(msg);

                    if (!target) return sendPlayerMessage(player, `§8[§cX§8] §cFailed to find player as they don't exist or aren't online (${msg})`);
                    sendPlayerMessage(player, `§f${target.name}§a's current heart count is §f${getScore(target, `ls-death`)}`);
                }
                heartGet();
                break;
            case `gain`:
                if (staffCheck(player, `§8[§cX§8] §cYou are not allowed to use this command!`)) return;

                function heartglGain() {
                    if (!args[0]) return sendPlayerMessage(player, `§aHearts gained is set to §f${lifesteal.get(`heartgain`)}`);

                    if (isNaN(+args[0])) return sendPlayerMessage(player, `§8[§cX§8] §cMust be a number!`);
                    lifesteal.set(`heartgain`, args[0].toLowerCase());

                    sendPlayerMessage(player, `§8[§a/§8] §aSet hearts gained to §f${args[0]}`);
                }
                heartglGain();
                break;
            case `lose`:
                if (staffCheck(player, `§8[§cX§8] §cYou are not allowed to use this command!`)) return;

                function heartglLose() {
                    if (!args[0]) return sendPlayerMessage(player, `§aHearts lost is set to §f${lifesteal.get(`heartlose`)}`);

                    if (isNaN(+args[0])) return sendPlayerMessage(player, `§8[§cX§8] §cMust be a number!`);
                    lifesteal.set(`heartlose`, args[0].toLowerCase());

                    sendPlayerMessage(player, `§8[§a/§8] §aSet hearts lost to §f${args[0]}`);
                }
                heartglLose();
                break;
        }
    }
});