import Item, { ItemType, type ItemTypeImage } from "./item";
import Character from "./character";
import { SpinnerAction } from "./spinner";
import Tile from "./tile";

export default class Player extends Character {
    public health: number;
    public lastDoor: Tile | undefined;
    public active = true;

    private inventory: Item[] = [];

    constructor(type: ItemTypeImage) {
        super(type);
        this.health = this.maxHealth;
        const defaultItem = this.defaultItem;
        if (defaultItem) {
            this.inventory.push(this.defaultItem);
        }
    }

    get maxHealth() {
        return this.type === ItemType.CHAR_BIG ? 7 : 5;
    }

    get defaultItem() {
        if (this.type === ItemType.CHAR_NINJA) {
            return new Item(ItemType.WEAPON_KNIFE);
        }
        if (this.type === ItemType.CHAR_POLICE) {
            return new Item(ItemType.WEAPON_PISTOL);
        }
        return null;
    }

    get healingAmount() {
        return this.type === ItemType.CHAR_NURSE ? 2 : 1;
    }

    get isDead() {
        return this.health <= 0;
    }

    get meleeWeapon() {
        return this.inventory.find(i => i.isMeleeWeapon);
    }

    get rangedWeapon() {
        return this.inventory.find(i => i.isRangedWeapon);
    }

    get grenade() {
        return this.inventory.find(i => i.type === ItemType.WEAPON_GRENADE);
    }

    get rocketLauncher() {
        return this.inventory.find(i => i.type === ItemType.WEAPON_ROCKET_LAUNCHER);
    }

    get keys() {
        return this.inventory.find(i => i.type === ItemType.ITEM_KEYS);
    }

    get fuel() {
        return this.inventory.find(i => i.type === ItemType.ITEM_FUEL);
    }

    get healingKit() {
        return this.inventory.find(i => i.type === ItemType.ITEM_HEALING_KIT);
    }

    public heal(patient: Player) {
        patient.health += this.healingAmount;
    }

    public addItem(item: Item | null | undefined) {
        if (item) {
            this.inventory.push(item);
        }
    }

    public getItem(i: number) {
        return this.inventory[i];
    }

    public spendItem(item: Item | null | undefined): boolean {
        if (!item) return false;
        if (item.isSpendingWeapon) return this.removeItem(item);

        return true;
    }

    public removeItem(item: Item | null | undefined): boolean {
        if (!item) {
            return false;
        }
        const itemIndex = this.inventory.findIndex(i => i === item);

        if (itemIndex >= 0) {
            this.inventory.splice(itemIndex, 1);
            return true;
        }

        return false;
    }

    public removeAllItems(): Item[] {
        const inventory = this.inventory.slice();
        this.inventory = [];
        return inventory;
    }

    public hasItem(item: Item | ItemTypeImage | null | undefined): boolean {
        if (!item) {
            return false;
        }
        const itemIndex = this.inventory.findIndex(i => i === item || i.type === item);

        return itemIndex >= 0;
    }

    public get hasAnyItems() {
        return this.inventory.length > 0;
    }

    public get numItems() {
        return this.inventory.length;
    }

    public [Symbol.iterator]() {
        return this.inventory.slice()[Symbol.iterator]();
    }

    public toggleActive() {
        this.active = !this.active;
    }

    /** @returns true, if action was performed */
    public handleSpin(action: SpinnerAction): boolean {
        const enemy = this.tile.enemy;

        switch (action) {
            case SpinnerAction.RUN:
                return true;

            case SpinnerAction.BITE:
                this.health -= 1;
                return true;

            case SpinnerAction.MELEE:
                if (!enemy) return false;
                if (enemy.isBoss) return false;
                if (enemy.isFlyingEnemy) return false;

                return this.spendItem(this.meleeWeapon);

            case SpinnerAction.SHOOT:
                if (!enemy) return false;
                if (enemy.isBoss) return false;

                return this.spendItem(this.rangedWeapon);
        }
    }
}

export const Players = {
    BIG: new Player(ItemType.CHAR_BIG),
    NINJA: new Player(ItemType.CHAR_NINJA),
    NURSE: new Player(ItemType.CHAR_NURSE),
    POLICE: new Player(ItemType.CHAR_POLICE),
    RUNNER: new Player(ItemType.CHAR_RUNNER),
} as const;
