import { BrickDisplay, type BrickDisplayImage } from "@common/display/brick";
import { choice, shuffle } from "@common/utils";

const emptySprite: BrickDisplayImage = { image: [], width: 0, height: 0 };

export interface Item {
    sprite: BrickDisplayImage;
    damage: number;
    accuracy: number;
    heal?: number;
    instantUse?: boolean;
    consumable?: boolean;
    ranged: boolean;
}

export interface Monster {
    sprite: BrickDisplayImage;
    damage: number;
    accuracy: number;
    health: number;
    maxHealth: number;
    ranged: boolean;
    lootTable: Partial<Record<Items, number>>; // <itemId, probability of drop>
    secondLootChance: number;
}

export enum Items {
    STICK,
    SWORD,
    HEAVY_SWORD,
    BOW,
    GRENADE,
    POTION,
    HEAL,
}

export enum Monsters {
    SMALL_SLIME,
    SMALL_DEMON,
    SNAKE,
    SMALL_ELEMENTAL,
    SLIME,
    DEMON,
    ELEMENTAL,
    BIG_SLIME,
    BIG_ELEMENTAL,
}

export const ITEMS: Item[] = [
    { // STICK
        sprite: emptySprite,
        damage: 1,
        accuracy: 1,
        ranged: false,
    },
    { // SWORD
        sprite: emptySprite,
        accuracy: 0.8,
        damage: 5,
        ranged: false,
    },
    { // BIG_SWORD
        sprite: emptySprite,
        accuracy: 0.7,
        damage: 10,
        ranged: false,
    },
    { // BOW
        sprite: emptySprite,
        accuracy: 0.6,
        damage: 4,
        ranged: true,
    },
    { // GRENADE
        sprite: emptySprite,
        accuracy: 0.8,
        damage: 8,
        ranged: true,
        consumable: true,
    },
    { // POTION
        sprite: emptySprite,
        accuracy: 1,
        damage: 0,
        heal: 10,
        ranged: false,
        consumable: true,
    },
    { // HEAL
        sprite: emptySprite,
        accuracy: 1,
        damage: 0,
        heal: 5,
        ranged: false,
        instantUse: true,
    },
];
export const MONSTERS: Monster[] = [
    { // SMALL_SLIME
        sprite: emptySprite,
        health: 1,
        maxHealth: 1,
        damage: 1,
        accuracy: 0.5,
        lootTable: {
            [Items.HEAL]: 0.5,
            [Items.SWORD]: 0.3,
            [Items.POTION]: 0.15,
            [Items.BOW]: 0.05,
        },
        ranged: false,
        secondLootChance: 0,
    },
    { // SMALL_DEMON
        sprite: emptySprite,
        health: 2,
        maxHealth: 2,
        damage: 1,
        accuracy: 0.7,
        lootTable: {
            [Items.HEAL]: 0.5,
            [Items.SWORD]: 0.3,
            [Items.POTION]: 0.15,
            [Items.BOW]: 0.04,
            [Items.HEAVY_SWORD]: 0.01,
        },
        ranged: false,
        secondLootChance: 0,
    },
    { // SNAKE
        sprite: emptySprite,
        health: 3,
        maxHealth: 3,
        damage: 2,
        accuracy: 0.8,
        lootTable: {
            [Items.HEAL]: 0.5,
            [Items.POTION]: 0.3,
            [Items.BOW]: 0.1,
            [Items.GRENADE]: 0.01,
        },
        ranged: false,
        secondLootChance: 0,
    },
    { // SMALL_ELEMENTAL
        sprite: emptySprite,
        health: 4,
        maxHealth: 4,
        damage: 2,
        accuracy: 0.5,
        lootTable: {
            [Items.HEAL]: 0.5,
            [Items.BOW]: 0.3,
            [Items.GRENADE]: 0.1,
        },
        ranged: true,
        secondLootChance: 0,
    },
    { // SLIME
        sprite: emptySprite,
        health: 5,
        maxHealth: 5,
        damage: 3,
        accuracy: 0.6,
        lootTable: {
            [Items.HEAL]: 0.5,
            [Items.SWORD]: 0.3,
            [Items.POTION]: 0.15,
            [Items.BOW]: 0.05,
            [Items.HEAVY_SWORD]: 0.01,
        },
        ranged: false,
        secondLootChance: 0.3,
    },
    { // DEMON
        sprite: emptySprite,
        health: 6,
        maxHealth: 6,
        damage: 3,
        accuracy: 0.8,
        lootTable: {
            [Items.HEAL]: 0.5,
            [Items.SWORD]: 0.3,
            [Items.POTION]: 0.15,
            [Items.BOW]: 0.1,
            [Items.HEAVY_SWORD]: 0.05,
        },
        ranged: false,
        secondLootChance: 0.3,
    },
    { // ELEMENTAL
        sprite: emptySprite,
        health: 7,
        maxHealth: 7,
        damage: 4,
        accuracy: 0.5,
        lootTable: {
            [Items.HEAL]: 0.2,
            [Items.POTION]: 0.2,
            [Items.BOW]: 0.3,
            [Items.GRENADE]: 0.2,
        },
        ranged: true,
        secondLootChance: 0.3,
    },
    { // BIG_SLIME
        sprite: emptySprite,
        health: 10,
        maxHealth: 10,
        damage: 5,
        accuracy: 0.6,
        lootTable: {
            [Items.HEAL]: 0.5,
            [Items.SWORD]: 0.3,
            [Items.POTION]: 0.2,
            [Items.BOW]: 0.3,
            [Items.GRENADE]: 0.2,
            [Items.HEAVY_SWORD]: 0.1,
        },
        ranged: false,
        secondLootChance: 0.7,
    },
    { // BIG_ELEMENTAL
        sprite: emptySprite,
        health: 20,
        maxHealth: 20,
        damage: 6,
        accuracy: 0.9,
        lootTable: {},
        ranged: true,
        secondLootChance: 0,
    },
];

export const MONSTERS_ORDER = [
    ...shuffle([Monsters.SMALL_SLIME, Monsters.SMALL_DEMON, Monsters.SNAKE]),
    Monsters.SMALL_ELEMENTAL,
    choice([Monsters.SMALL_SLIME, Monsters.SMALL_DEMON, Monsters.SNAKE]),

    ...shuffle([Monsters.SLIME, Monsters.DEMON]),
    Monsters.ELEMENTAL,
    choice([Monsters.SLIME, Monsters.DEMON]),

    Monsters.BIG_SLIME,
    choice([
        Monsters.SMALL_SLIME,
        Monsters.SMALL_DEMON,
        Monsters.SNAKE,
        Monsters.SMALL_ELEMENTAL,
        Monsters.SLIME,
        Monsters.DEMON,
        Monsters.ELEMENTAL,
    ]),
    Monsters.BIG_ELEMENTAL,
];

export function loadData(spritesheet: BrickDisplayImage) {
    for (let i = 0; i < ITEMS.length; i++) {
        ITEMS[i].sprite = BrickDisplay.extractSprite(spritesheet, i * 4, 0, 4, 4);
    }

    for (let i = 0; i < MONSTERS.length; i++) {
        const x = (i % 8) << 2;
        const y = (2 + i / 8) << 2;
        MONSTERS[i].sprite = BrickDisplay.extractSprite(spritesheet, x, y, 4, 4);
    }
}