import { anthill } from "./anthill.js";
import { controls } from "./controls.js";
import { loadJson } from "./loadJson.js";
import { loadSprite } from "./loadSprite.js";
import { shop } from "./shop.js";
import { tutorial } from "./tutorial.js";

export class AnthillUi {
    constructor() {
        this.layout = {
            width: 512,
            height: 512,
            buttons: [
                {
                    key: "red",
                    label: "RedAntButton",
                    x: 62,
                    y: 45,
                    width: 121,
                    height: 125
                },
                {
                    key: "green",
                    label: "GreenAntButton",
                    x: 194,
                    y: 39,
                    width: 118,
                    height: 105
                },
                {
                    key: "yellow",
                    label: "YellowAntButton",
                    x: 322,
                    y: 44,
                    width: 135,
                    height: 100
                },
                {
                    key: "purple",
                    label: "PurpleAntButton",
                    x: 24,
                    y: 191,
                    width: 138,
                    height: 139
                },
                {
                    key: "blue",
                    label: "BlueAntButton",
                    x: 340,
                    y: 155,
                    width: 142,
                    height: 156
                },
                {
                    key: "signalant",
                    label: "SignalantButton",
                    x: 49,
                    y: 333,
                    width: 427,
                    height: 133
                }
            ],
            price: {
                x: 204,
                y: 225,
                width: 109,
                height: 36,
                labelOffsetY: 16
            },
            descriptionPadding: 14,
            titleY: 20
        };
        this.statButtons = {
            speed: this.layout.buttons[0],
            maxTravelDistance: this.layout.buttons[2],
            harvestValue: this.layout.buttons[3],
            respawnTime: this.layout.buttons[4]
        };
        this.statPrecision = {
            speed: 1,
            maxTravelDistance: 0,
            harvestValue: 0,
            respawnTime: 0
        };
        this.statButtonOrder = ["speed", "maxTravelDistance", "harvestValue", "respawnTime"];
        this.basePanelSprites = {
            1: loadSprite("assets/ui/AnthillUi_1.png"),
            2: loadSprite("assets/ui/AnthillUi_2.png"),
            3: loadSprite("assets/ui/AnthillUi_3.png"),
            4: loadSprite("assets/ui/AnthillUi_4.png"),
            5: loadSprite("assets/ui/AnthillUi.png")
        };
        this.hiddenSignalantOverlaySprite = loadSprite("assets/ui/AnthillUi_hideSignalAnts.png");
        this.upgradePanelSprites = {
            red: loadSprite("assets/ui/anthillUi_redAnt.png"),
            green: loadSprite("assets/ui/anthillUi_greenAnt.png"),
            yellow: loadSprite("assets/ui/anthillUi_yellowAnt.png"),
            purple: loadSprite("assets/ui/anthillUi_purpleAnt.png"),
            blue: loadSprite("assets/ui/anthillUi_blueAnt.png")
        };
        this.signalantPanelSprite = loadSprite("assets/ui/anthillUi_signalAnt.png");
        this.isOpen = false;
        this.view = "base";
        this.selectedColor = null;
        this.descriptionConfig = {};
        this.x = 0;
        this.y = 0;

        loadJson("data/antUpgradeDescriptions.json")
            .then(config => {
                this.descriptionConfig = config || {};
            })
            .catch(() => {
                this.descriptionConfig = {};
            });
    }

    reposition() {
        this.x = Math.round((window.innerWidth - this.layout.width) / 2);
        this.y = Math.round((window.innerHeight - this.layout.height) / 2);
    }

    open() {
        this.isOpen = true;
        this.view = "base";
        this.selectedColor = null;
    }

    close() {
        this.isOpen = false;
        this.view = "base";
        this.selectedColor = null;
        tutorial.trigger("anthill.close");
    }

    toggleOpen() {
        this.isOpen = !this.isOpen;
    }

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

    getButtonRect(button) {
        return {
            x: this.x + button.x,
            y: this.y + button.y,
            width: button.width,
            height: button.height
        };
    }

    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.isOpen && this.isPointInRect(x, y, this.getPanelRect());
    }

    isWorldPointInsideAnthill(worldX, worldY) {
        return worldX >= anthill.x - anthill.width / 2
            && worldX <= anthill.x + anthill.width / 2
            && worldY >= anthill.y - anthill.height / 2
            && worldY <= anthill.y + anthill.height / 2;
    }

    handleAnthillLeftClick(worldX, worldY) {
        if (!this.isWorldPointInsideAnthill(worldX, worldY)) {
            return false;
        }

        if (this.isOpen) {
            this.close();
        } else {
            this.open();
            tutorial.trigger("anthill.open");
        }
        return true;
    }

    handleOutsideLeftClick(x, y) {
        if (!this.isOpen || this.isPointInside(x, y)) {
            return false;
        }

        this.close();
        return true;
    }

    handleLeftClick(x, y) {
        if (!this.isOpen || !this.isPointInside(x, y)) {
            return false;
        }

        if (this.view === "base") {
            return this.handleBaseLeftClick(x, y);
        }

        if (this.view === "signalant") {
            return this.handleSignalantLeftClick(x, y);
        }

        return this.handleUpgradeLeftClick(x, y);
    }

    handleBaseLeftClick(x, y) {
        for (const button of this.layout.buttons) {
            if (!this.isPointInRect(x, y, this.getButtonRect(button))) {
                continue;
            }

            if (button.key === "signalant") {
                if (!anthill.canAccessSignalants()) {
                    return true;
                }

                this.view = "signalant";
                shop.ensureSignalantOffers();
                tutorial.trigger("anthill.signalant.open");
                return true;
            }

            if (!anthill.isColorUnlocked(button.key)) {
                return true;
            }

            this.view = "upgrade";
            this.selectedColor = button.key;
            if (button.key === "red") {
                tutorial.trigger("anthill.red.open");
            }
            return true;
        }

        return true;
    }

    handleSignalantLeftClick(x, y) {
        const offerButtons = [this.layout.buttons[0], this.layout.buttons[1], this.layout.buttons[2]];
        for (let index = 0; index < offerButtons.length; index++) {
            if (this.isPointInRect(x, y, this.getButtonRect(offerButtons[index]))) {
                return shop.buySignalantOffer(index);
            }
        }

        const backButton = this.layout.buttons[3];
        if (this.isPointInRect(x, y, this.getButtonRect(backButton))) {
            this.view = "base";
            tutorial.trigger("anthill.signalant.close");
            tutorial.trigger("anthill.base.view");
            return true;
        }

        return true;
    }

    handleUpgradeLeftClick(x, y) {
        const backButton = this.layout.buttons[1];
        if (this.isPointInRect(x, y, this.getButtonRect(backButton))) {
            this.view = "base";
            this.selectedColor = null;
            tutorial.trigger("anthill.base.view");
            return true;
        }

        const antId = this.getSelectedAntId();
        if (!antId) {
            return true;
        }

        for (const statKey of this.statButtonOrder) {
            const button = this.statButtons[statKey];
            if (this.isPointInRect(x, y, this.getButtonRect(button))) {
                const didUpgrade = anthill.upgradeStat(antId, statKey);
                if (didUpgrade && this.selectedColor === "red") {
                    tutorial.trigger("anthill.red.upgrade");
                }
                return didUpgrade;
            }
        }

        return true;
    }

    getSelectedAntId() {
        if (!this.selectedColor) {
            return null;
        }

        if (!anthill.isColorUnlocked(this.selectedColor)) {
            return null;
        }

        return anthill.getAntIdByColor(this.selectedColor);
    }

    getHoveredButton(x, y) {
        if (!this.isOpen || !this.isPointInside(x, y)) {
            return null;
        }

        for (const button of this.layout.buttons) {
            if (this.isPointInRect(x, y, this.getButtonRect(button))) {
                return button;
            }
        }

        return null;
    }

    getHoveredStatKey() {
        if (this.view !== "upgrade") {
            return null;
        }

        const hoveredButton = this.getHoveredButton(controls.mouse.x, controls.mouse.y);
        if (!hoveredButton) {
            return null;
        }

        for (const statKey of this.statButtonOrder) {
            if (this.statButtons[statKey] === hoveredButton) {
                return statKey;
            }
        }

        return null;
    }

    getHoveredShopIndex() {
        if (this.view !== "signalant") {
            return null;
        }

        const hoveredButton = this.getHoveredButton(controls.mouse.x, controls.mouse.y);
        if (!hoveredButton) {
            return null;
        }

        const offerButtons = [this.layout.buttons[0], this.layout.buttons[1], this.layout.buttons[2]];
        const hoveredIndex = offerButtons.indexOf(hoveredButton);
        return hoveredIndex === -1 ? null : hoveredIndex;
    }

    getHoveredShopSignalant() {
        const hoveredIndex = this.getHoveredShopIndex();
        const offers = shop.getSignalantOffers();
        if (hoveredIndex !== null) {
            return offers[hoveredIndex] || null;
        }

        return offers[0] || null;
    }

    formatStatValue(statKey, value) {
        if (!Number.isFinite(value)) {
            return "0";
        }

        const precision = this.statPrecision[statKey] ?? 0;
        if (precision <= 0) {
            return String(Math.round(value));
        }

        return value.toFixed(precision);
    }

    getStatLabel(statKey) {
        return this.descriptionConfig[statKey]?.label || statKey;
    }

    getStatDescription(statKey) {
        return this.descriptionConfig[statKey]?.description || "";
    }

    drawCenteredText(ctx, text, x, y, options = {}) {
        ctx.save();
        ctx.fillStyle = options.color || "#C0C0C0";
        ctx.font = options.font || "bold 16px monospace";
        ctx.textAlign = "center";
        ctx.textBaseline = "middle";
        ctx.fillText(text, x, y);
        ctx.restore();
    }

    drawWrappedText(ctx, text, x, y, maxWidth, lineHeight) {
        const words = String(text || "").split(/\s+/);
        const lines = [];
        let currentLine = "";

        for (const word of words) {
            const nextLine = currentLine ? `${currentLine} ${word}` : word;
            if (ctx.measureText(nextLine).width <= maxWidth || !currentLine) {
                currentLine = nextLine;
            } else {
                lines.push(currentLine);
                currentLine = word;
            }
        }

        if (currentLine) {
            lines.push(currentLine);
        }

        lines.forEach((line, index) => {
            ctx.fillText(line, x, y + index * lineHeight);
        });
    }

    drawUpgradeValues(ctx) {
        const antId = this.getSelectedAntId();
        if (!antId) {
            return;
        }

        const hoveredStatKey = this.getHoveredStatKey();

        for (const statKey of this.statButtonOrder) {
            const button = this.statButtons[statKey];
            const rect = this.getButtonRect(button);
            const preview = anthill.getUpgradePreview(antId, statKey);

            if (!preview) {
                continue;
            }

            this.drawCenteredText(
                ctx,
                this.formatStatValue(statKey, preview.currentValue),
                rect.x + rect.width / 2,
                rect.y + rect.height / 2 - (hoveredStatKey === statKey ? 10 : 0),
                { font: "bold 18px monospace" }
            );

            if (hoveredStatKey === statKey) {
                this.drawCenteredText(
                    ctx,
                    this.formatStatValue(statKey, preview.nextValue),
                    rect.x + rect.width / 2,
                    rect.y + rect.height / 2 + 18,
                    { font: "bold 12px monospace", color: "#E5D5AA" }
                );
            }
        }

        const backRect = this.getButtonRect(this.layout.buttons[1]);
        this.drawCenteredText(ctx, "BACK", backRect.x + backRect.width / 2, backRect.y + backRect.height / 2, {
            font: "bold 18px monospace"
        });
    }

    drawPrice(ctx) {
        let purchaseKey = null;
        if (this.view === "upgrade") {
            purchaseKey = this.getSelectedAntId();
        } else if (this.view === "signalant") {
            purchaseKey = anthill.getSignalantPurchaseKey();
        }

        if (!purchaseKey) {
            return;
        }

        const priceRect = {
            x: this.x + this.layout.price.x,
            y: this.y + this.layout.price.y,
            width: this.layout.price.width,
            height: this.layout.price.height
        };

        this.drawCenteredText(ctx, "Price", priceRect.x + priceRect.width / 2, priceRect.y - this.layout.price.labelOffsetY, {
            font: "bold 14px monospace",
            color: "#E5D5AA"
        });
        this.drawCenteredText(ctx, String(anthill.getNextPurchaseCost(purchaseKey)), priceRect.x + priceRect.width / 2, priceRect.y + priceRect.height / 2, {
            font: "bold 18px monospace"
        });
    }

    drawBaseUnlockHint(ctx) {
        const nextUnlock = anthill.getNextUnlock();
        const priceRect = {
            x: this.x + this.layout.price.x,
            y: this.y + this.layout.price.y,
            width: this.layout.price.width,
            height: this.layout.price.height
        };

        if (!nextUnlock) {
            this.drawCenteredText(ctx, "All ants unlocked", priceRect.x + priceRect.width / 2, priceRect.y + priceRect.height / 2 - 8, {
                font: "bold 16px monospace",
                color: "#E5D5AA"
            });
            this.drawCenteredText(ctx, `${anthill.getTotalPurchaseCount()} buys spent`, priceRect.x + priceRect.width / 2, priceRect.y + priceRect.height / 2 + 14, {
                font: "12px monospace"
            });
            return;
        }

        const remainingBuyLabel = nextUnlock.remainingBuys === 1 ? "buy" : "buys";
        const antColorLabel = `${String(nextUnlock.antDefinition.color || "").replace(/^./, character => character.toUpperCase())} Ant`;

        this.drawCenteredText(ctx, antColorLabel, priceRect.x + priceRect.width / 2, priceRect.y + priceRect.height / 2 - 8, {
            font: "bold 12px monospace",
            color: "#E5D5AA"
        });
        this.drawCenteredText(ctx, `in ${nextUnlock.remainingBuys} ${remainingBuyLabel}`, priceRect.x + priceRect.width / 2, priceRect.y + priceRect.height / 2 + 14, {
            font: "bold 16px monospace"
        });
    }

    drawDescription(ctx) {
        const descriptionButton = this.layout.buttons[5];
        const rect = this.getButtonRect(descriptionButton);
        const hoveredStatKey = this.getHoveredStatKey();
        const antId = this.getSelectedAntId();
        const antDefinition = antId ? anthill.getAntDefinition(antId) : null;

        ctx.save();
        ctx.fillStyle = "#C0C0C0";
        ctx.textAlign = "left";
        ctx.textBaseline = "top";

        const textX = rect.x + this.layout.descriptionPadding;
        const textY = rect.y + this.layout.descriptionPadding;
        const textWidth = rect.width - this.layout.descriptionPadding * 2;
        const contentX = textX + 2;
        const contentY = textY + 4;
        const headingX = contentX + 2;
        const headingY = contentY + 8;

        if (!hoveredStatKey || !antId) {
            ctx.font = "bold 14px monospace";
            ctx.fillText(antDefinition?.name || "Select an ant upgrade", headingX, headingY);
            ctx.font = "12px monospace";
            this.drawWrappedText(ctx, "Hover a stat to preview the next +10% upgrade and click to buy it.", contentX, contentY + 32, textWidth, 16);
            ctx.restore();
            return;
        }

        ctx.font = "bold 14px monospace";
        ctx.fillText(this.getStatLabel(hoveredStatKey), headingX, headingY);

        ctx.font = "12px monospace";
        this.drawWrappedText(ctx, this.getStatDescription(hoveredStatKey), contentX, contentY + 32, textWidth, 16);

        ctx.restore();
    }

    drawSignalantOffers(ctx) {
        const offers = shop.getSignalantOffers();
        const offerButtons = [this.layout.buttons[0], this.layout.buttons[1], this.layout.buttons[2]];

        offerButtons.forEach((button, index) => {
            const offer = offers[index];
            if (!offer) {
                return;
            }

            const rect = this.getButtonRect(button);
            const scale = 3;
            const drawWidth = offer.width * scale;
            const drawHeight = offer.height * scale;
            const drawX = Math.round(rect.x + (rect.width - drawWidth) / 2);
            const drawY = Math.round(rect.y + (rect.height - drawHeight) / 2);
            offer.drawAt(ctx, drawX, drawY, scale, { animateSignal: false });
        });
    }

    drawSignalantBackButton(ctx) {
        const backRect = this.getButtonRect(this.layout.buttons[3]);
        this.drawCenteredText(ctx, "BACK", backRect.x + backRect.width / 2, backRect.y + backRect.height / 2, {
            font: "bold 18px monospace"
        });
    }

    drawSignalantDescription(ctx) {
        const rect = this.getButtonRect(this.layout.buttons[5]);
        const signalant = this.getHoveredShopSignalant();

        ctx.save();
        ctx.fillStyle = "#C0C0C0";
        ctx.textAlign = "left";
        ctx.textBaseline = "top";
        ctx.font = "bold 14px monospace";

        const textX = rect.x + this.layout.descriptionPadding + 4;
        const textY = rect.y + this.layout.descriptionPadding + 12;
        const textWidth = rect.width - this.layout.descriptionPadding * 2;

        if (!signalant) {
                ctx.fillText("Pheromone Ant", textX, textY);
            ctx.font = "12px monospace";
            this.drawWrappedText(ctx, "Choose one of the three, you can't have them all.", textX, textY + 24, textWidth, 16);
            ctx.restore();
            return;
        }

        const colorsText = signalant.affectsColors.map(color => color.toUpperCase()).join(", ") || "NONE";
            ctx.fillText("Pheromone Ant", textX, textY);
        ctx.font = "12px monospace";
        this.drawWrappedText(ctx, "Choose one of the three, you can't have them all.", textX, textY + 24, textWidth, 16);
        this.drawWrappedText(ctx, `Colors: ${colorsText}`, textX, textY + 44, textWidth, 16);
        this.drawWrappedText(ctx, `Range: ${Math.round(signalant.affectionRadius)}`, textX, textY + 64, textWidth, 16);
        ctx.restore();
    }

    drawSignalantShop(ctx) {
        this.drawCenteredText(ctx, "PHEROMONE ANT", this.x + this.layout.width / 2, this.y + this.layout.titleY, {
            font: "bold 16px monospace",
            color: "#E5D5AA"
        });
        this.drawSignalantOffers(ctx);
        this.drawSignalantBackButton(ctx);
        this.drawPrice(ctx);
        this.drawSignalantDescription(ctx);
    }

    drawHiddenSignalantOverlay(ctx) {
        if (this.view !== "base") {
            return;
        }

        if (anthill.canAccessSignalants()) {
            return;
        }

        if (!this.hiddenSignalantOverlaySprite || !this.hiddenSignalantOverlaySprite.complete) {
            return;
        }

        ctx.drawImage(this.hiddenSignalantOverlaySprite, this.x, this.y, this.layout.width, this.layout.height);
    }

    getCurrentPanelSprite() {
        if (this.view === "signalant" && this.signalantPanelSprite) {
            return this.signalantPanelSprite;
        }

        if (this.view === "upgrade" && this.selectedColor && this.upgradePanelSprites[this.selectedColor]) {
            return this.upgradePanelSprites[this.selectedColor];
        }

        const unlockedAntCount = Math.max(1, Math.min(5, anthill.getUnlockedAntCount()));
        return this.basePanelSprites[unlockedAntCount] || this.basePanelSprites[5];
    }

    drawUpgradeHeader(ctx) {
        if (!this.selectedColor) {
            return;
        }

        const title = "ANT UPGRADE";
        this.drawCenteredText(ctx, title, this.x + this.layout.width / 2, this.y + this.layout.titleY, {
            font: "bold 16px monospace",
            color: "#E5D5AA"
        });
    }

    draw(ctx) {
        if (!this.isOpen) {
            return;
        }

        this.reposition();

        const panelSprite = this.getCurrentPanelSprite();

        if (!panelSprite || !panelSprite.complete) {
            return;
        }

        ctx.drawImage(panelSprite, this.x, this.y, this.layout.width, this.layout.height);
        this.drawHiddenSignalantOverlay(ctx);

        if (this.view === "upgrade") {
            this.drawUpgradeHeader(ctx);
            this.drawUpgradeValues(ctx);
            this.drawPrice(ctx);
            this.drawDescription(ctx);
            return;
        }

        if (this.view === "signalant") {
            this.drawSignalantShop(ctx);
            return;
        }

        if (this.view === "base") {
            this.drawBaseUnlockHint(ctx);
        }
    }
}

export const anthillUi = new AnthillUi();