import { loadSprite } from "./loadSprite.js";
import { sharedMessage } from "./message.js";
import { storage } from "./storage.js";
import { addSignalant, removeSignalant } from "./signalant.js";
import { sfx } from "./sfx.js";
import { tutorial } from "./tutorial.js";

export class StorageUi {
    constructor() {
        this.layout = {
            margin: 10,
            width: 900,
            height: 110,
            visibleSlots: 10,
            slotSize: 70,
            contentOffsetY: 23,
            slotOffsetX: 44,
            slotOffsetY: 31,
            slotSpacing: 81,
            iconOffsetX: 48,
            iconOffsetY: 35,
            iconScale: 3,
            arrowWidth: 16 * 3,
            arrowHeight: 29 * 3,
            messageX: 11,
            messageY: 4,
            messageWidth: 878,
            messageHeight: 19
        };
        this.panelSprite = loadSprite("assets/ui/signalantStorage.png");
        this.message = sharedMessage;
        this.message.setBounds(0, this.layout.messageWidth);
        this.index = 0;
        this.x = 0;
        this.y = 0;
    }

    reposition() {
        this.x = this.layout.margin;
        this.y = window.innerHeight - this.layout.margin - this.layout.height;
    }

    getPanelRect() {
        return {
            x: this.x,
            y: this.y,
            width: this.layout.width,
            height: this.layout.height
        };
    }

    getSlotRect(index) {
        return {
            x: this.x + this.layout.slotOffsetX + index * this.layout.slotSpacing,
            y: this.y + this.layout.slotOffsetY,
            width: this.layout.slotSize,
            height: this.layout.slotSize
        };
    }

    getLeftArrowRect() {
        return {
            x: this.x,
            y: this.y + this.layout.contentOffsetY,
            width: this.layout.arrowWidth,
            height: this.layout.arrowHeight
        };
    }

    getRightArrowRect() {
        return {
            x: this.x + this.layout.width - this.layout.arrowWidth,
            y: this.y + this.layout.contentOffsetY,
            width: this.layout.arrowWidth,
            height: this.layout.arrowHeight
        };
    }

    setMessage(text) {
        this.message.setNextMessage(text);
    }

    isPointInRect(x, y, rect) {
        return x >= rect.x && x <= rect.x + rect.width && y >= rect.y && y <= rect.y + rect.height;
    }

    isPointInside(x, y) {
        return this.isPointInRect(x, y, this.getPanelRect());
    }

    getVisibleCount(signalants) {
        return Math.min(signalants.length, this.layout.visibleSlots);
    }

    normalizeIndex(signalantCount) {
        if (signalantCount <= 0) {
            this.index = 0;
            return;
        }

        this.index = ((this.index % signalantCount) + signalantCount) % signalantCount;
    }

    getVisibleEntries(signalants) {
        this.normalizeIndex(signalants.length);

        const entries = [];
        const visibleCount = this.getVisibleCount(signalants);

        for (let slotIndex = 0; slotIndex < visibleCount; slotIndex++) {
            const storageIndex = (this.index + slotIndex) % signalants.length;
            entries.push({
                slotIndex,
                storageIndex,
                signalant: signalants[storageIndex]
            });
        }

        return entries;
    }

    syncSignalantActiveState(ui) {
        for (const signalant of storage.signalants) {
            signalant.isActive = signalant === ui.activeSignalant || signalant === ui.ghostSignalant;
        }
    }

    indexUp(signalantCount) {
        if (signalantCount > 0) {
            this.index = (this.index - 1 + signalantCount) % signalantCount;
            this.setMessage("Previous stored signalants");
        }
    }

    indexDown(signalantCount) {
        if (signalantCount > 0) {
            this.index = (this.index + 1) % signalantCount;
            this.setMessage("Next stored signalants");
        }
    }

    getClickAction(x, y, signalants) {
        if (!this.isPointInside(x, y)) {
            return null;
        }

        if (signalants.length > this.layout.visibleSlots) {
            if (this.isPointInRect(x, y, this.getLeftArrowRect())) {
                return { type: "index-up" };
            }

            if (this.isPointInRect(x, y, this.getRightArrowRect())) {
                return { type: "index-down" };
            }
        }

        for (const entry of this.getVisibleEntries(signalants)) {
            if (this.isPointInRect(x, y, this.getSlotRect(entry.slotIndex))) {
                return {
                    type: "pick-signalant",
                    storageIndex: entry.storageIndex
                };
            }
        }

        return { type: "panel" };
    }

    pickUpSignalantFromStorage(ui, index) {
        const selectedSignalant = storage.takeSignalantAt(index);
        if (!selectedSignalant) {
            return false;
        }

        if (ui.ghostSignalant) {
            storage.addSignalant(ui.ghostSignalant);
        }

        ui.setGhostSignalant(selectedSignalant);
        ui.setActiveSignalant(null);
        this.normalizeIndex(storage.signalants.length);
        this.setMessage(`Picked signalant ${selectedSignalant.id} from storage`);
        tutorial.trigger("signalant.ghost");
        return true;
    }

    storeCurrentSignalant(ui) {
        if (ui.activeSignalant) {
            const storedSignalant = ui.activeSignalant;
            removeSignalant(ui.activeSignalant);
            storage.addSignalant(ui.activeSignalant);
            ui.setActiveSignalant(null);
            this.normalizeIndex(storage.signalants.length);
            this.setMessage(`Stored signalant ${storedSignalant.id}`);
            sfx.play("pheromoneAntStored");
            tutorial.trigger("signalant.store");
            return true;
        }

        if (ui.ghostSignalant) {
            const storedSignalant = ui.ghostSignalant;
            storage.addSignalant(ui.ghostSignalant);
            ui.setGhostSignalant(null);
            this.normalizeIndex(storage.signalants.length);
            this.setMessage(`Stored signalant ${storedSignalant.id}`);
            sfx.play("pheromoneAntStored");
            tutorial.trigger("signalant.store");
            return true;
        }

        return false;
    }

    placeGhostSignalant(ui, worldPosition) {
        if (!ui.ghostSignalant) {
            return false;
        }

        const placedSignalant = ui.ghostSignalant;
        ui.ghostSignalant.setPosition(worldPosition.x, worldPosition.y);
        addSignalant(ui.ghostSignalant);
        ui.setActiveSignalant(ui.ghostSignalant);
        ui.setGhostSignalant(null);
        this.setMessage(`Placed signalant ${placedSignalant.id}`);
        sfx.play("pheromoneAntPlaced");
        tutorial.trigger("signalant.place");
        return true;
    }

    replaceCurrentSignalant(ui) {
        if (!ui.activeSignalant) {
            return false;
        }

        const pickedSignalant = ui.activeSignalant;
        removeSignalant(ui.activeSignalant);
        ui.setGhostSignalant(ui.activeSignalant);
        ui.setActiveSignalant(null);
        this.setMessage(`Picked up signalant ${pickedSignalant.id}`);
        tutorial.trigger("signalant.ghost");
        return true;
    }

    handleLeftClick(x, y, ui) {
        const action = this.getClickAction(x, y, storage.signalants);
        if (!action) {
            return false;
        }

        if (action.type === "index-up") {
            this.indexUp(storage.signalants.length);
            return true;
        }

        if (action.type === "index-down") {
            this.indexDown(storage.signalants.length);
            return true;
        }

        if (action.type === "pick-signalant") {
            return this.pickUpSignalantFromStorage(ui, action.storageIndex);
        }

        return action.type === "panel";
    }

    handleRightClick(ui) {
        if (!ui.ghostSignalant) {
            return false;
        }

        return this.storeCurrentSignalant(ui);
    }

    drawGhostSignalant(ctx, cam, ghostSignalant, worldPosition) {
        if (!ghostSignalant) {
            return;
        }

        const originalX = ghostSignalant.x;
        const originalY = ghostSignalant.y;

        ghostSignalant.setPosition(worldPosition.x, worldPosition.y);
        ctx.save();
        ctx.globalAlpha = 0.65;
        ghostSignalant.draw(ctx, cam);
        ctx.restore();
        ghostSignalant.setPosition(originalX, originalY);
    }

    drawMessage(ctx) {
        ctx.save();
        ctx.fillStyle = "#3F2517";
        ctx.font = "bold 14px monospace";
        ctx.textAlign = "left";
        ctx.textBaseline = "middle";
        this.message.draw(
            ctx,
            this.x + this.layout.messageX,
            this.y + this.layout.messageY,
            this.layout.messageWidth,
            this.layout.messageHeight
        );
        ctx.restore();
    }

    draw(ctx) {
        const signalants = storage.signalants;
        this.reposition();
        this.normalizeIndex(signalants.length);
        ctx.drawImage(this.panelSprite, this.x, this.y, this.layout.width, this.layout.height);
        this.drawMessage(ctx);

        for (const entry of this.getVisibleEntries(signalants)) {
            const iconX = this.x + this.layout.iconOffsetX + entry.slotIndex * this.layout.slotSpacing;
            const iconY = this.y + this.layout.iconOffsetY;
            entry.signalant.drawAt(ctx, iconX, iconY, this.layout.iconScale, { animateSignal: false });
        }
    }
}

export const storageUi = new StorageUi();