import { signalantArray } from "./signalant.js";
import { controls } from "./controls.js";
import { cam } from "./cam.js";
import { statsUi } from "./statsUi.js";
import { statusUi } from "./statusUi.js";
import { storageUi } from "./storageUi.js";
import { queenUi } from "./queenUi.js";
import { anthillUi } from "./anthillUi.js";
import { soundUi } from "./soundUi.js";
import { sfx } from "./sfx.js";
import { tutorial } from "./tutorial.js";

export class Ui {
    constructor() {
        this.ghostSignalant = null;
        this.activeSignalant = null;
    }

    reposition() {
        queenUi.reposition();
        statsUi.reposition(queenUi.getPanelRect());
        storageUi.reposition();
        statusUi.reposition();
        anthillUi.reposition();
        soundUi.reposition();
    }

    syncSignalantActiveState() {
        const statusSignalant = statusUi.getSignalant(this);

        if (this.activeSignalant) {
            this.activeSignalant.isActive = this.activeSignalant === statusSignalant;
        }

        if (this.ghostSignalant) {
            this.ghostSignalant.isActive = this.ghostSignalant === statusSignalant;
        }

        for (const signalant of signalantArray) {
            if (signalant !== this.activeSignalant && signalant !== this.ghostSignalant) {
                signalant.isActive = false;
            }
        }

        storageUi.syncSignalantActiveState(this);
    }

    setActiveSignalant(signalant) {
        if (this.activeSignalant === signalant) {
            this.syncSignalantActiveState();
            return;
        }

        this.activeSignalant = signalant || null;
        this.syncSignalantActiveState();
    }

    setGhostSignalant(signalant) {
        this.ghostSignalant = signalant || null;
        this.syncSignalantActiveState();
    }

    hasExclusiveSignalantInteraction() {
        return Boolean(this.activeSignalant || this.ghostSignalant);
    }

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

    isMouseOverUi() {
        const mouseX = controls.mouse.x;
        const mouseY = controls.mouse.y;
        return queenUi.isPointInside(mouseX, mouseY)
            || statsUi.isPointInside(mouseX, mouseY)
            || storageUi.isPointInside(mouseX, mouseY)
            || statusUi.isPointInside(mouseX, mouseY, this)
            || anthillUi.isPointInside(mouseX, mouseY)
            || soundUi.isPointInside(mouseX, mouseY);
    }

    getMouseWorldPosition() {
        return {
            x: controls.mouse.x / cam.zoom - cam.x,
            y: controls.mouse.y / cam.zoom - cam.y
        };
    }

    getWorldScreenPosition(worldX, worldY) {
        return {
            x: Math.round((worldX + cam.x) * cam.zoom),
            y: Math.round((worldY + cam.y) * cam.zoom)
        };
    }

    rotateSignalantTowardMouse(signalant) {
        const screenPosition = this.getWorldScreenPosition(signalant.x, signalant.y);
        const dx = controls.mouse.x - screenPosition.x;
        const dy = controls.mouse.y - screenPosition.y;
        signalant.direction = Math.atan2(dy, dx) * 180 / Math.PI;
    }

    getSignalantAtScreenPoint(x, y) {
        for (let index = signalantArray.length - 1; index >= 0; index--) {
            const signalant = signalantArray[index];
            const screenPosition = this.getWorldScreenPosition(signalant.x, signalant.y);
            const halfWidth = Math.max(signalant.width * cam.zoom / 2, 18);
            const halfHeight = Math.max(signalant.height * cam.zoom / 2, 18);

            if (
                x >= screenPosition.x - halfWidth
                && x <= screenPosition.x + halfWidth
                && y >= screenPosition.y - halfHeight
                && y <= screenPosition.y + halfHeight
            ) {
                return signalant;
            }
        }

        return null;
    }

    update() {
        this.reposition();
        const activeStatusSignalant = statusUi.getSignalant(this);
        const tutorialAvoidRect = statusUi.isVisible(activeStatusSignalant) ? statusUi.getPanelRect() : null;

        soundUi.update();
        const consumedWheel = soundUi.handleWheel();

        const leftPressed = controls.wasMousePressed('left');
        let consumedLeftPress = false;
        let consumedRightPress = false;
        const rightPressed = controls.wasMousePressed('right');
        const mouseX = controls.mouse.x;
        const mouseY = controls.mouse.y;

        if (rightPressed) {
            consumedRightPress = storageUi.handleRightClick(this);
        }

        const isPheromoneAntMoving = !consumedRightPress && controls.mouse.buttons.right && this.activeSignalant && !this.activeSignalant.isFixed;

        if (isPheromoneAntMoving) {
            this.rotateSignalantTowardMouse(this.activeSignalant);
        }

        if (leftPressed) {
            const mouseWorldPosition = this.getMouseWorldPosition();
            const clickedAnthill = anthillUi.isWorldPointInsideAnthill(mouseWorldPosition.x, mouseWorldPosition.y);

            consumedLeftPress = queenUi.handleLeftClick(mouseX, mouseY);

            if (!consumedLeftPress) {
                consumedLeftPress = statsUi.handleLeftClick(mouseX, mouseY);
            }

            if (!consumedLeftPress) {
                consumedLeftPress = storageUi.handleLeftClick(mouseX, mouseY, this);
            }

            if (!consumedLeftPress) {
                consumedLeftPress = statusUi.handleLeftClick(mouseX, mouseY, this);
            }

            if (!consumedLeftPress) {
                consumedLeftPress = anthillUi.handleLeftClick(mouseX, mouseY);
            }

            if (!consumedLeftPress) {
                consumedLeftPress = soundUi.handleLeftClick(mouseX, mouseY);
            }

            if (!consumedLeftPress && soundUi.isOpen && !soundUi.isPointInside(mouseX, mouseY)) {
                soundUi.close();
            }

            if (!consumedLeftPress && clickedAnthill && this.ghostSignalant) {
                consumedLeftPress = storageUi.storeCurrentSignalant(this);
            }

            if (!consumedLeftPress && anthillUi.isOpen && !anthillUi.isPointInside(mouseX, mouseY)) {
                if (anthillUi.handleAnthillLeftClick(mouseWorldPosition.x, mouseWorldPosition.y)) {
                    consumedLeftPress = true;
                } else {
                    consumedLeftPress = anthillUi.handleOutsideLeftClick(mouseX, mouseY);
                }
            }

            if (!consumedLeftPress && !this.isMouseOverUi()) {
                consumedLeftPress = anthillUi.handleAnthillLeftClick(mouseWorldPosition.x, mouseWorldPosition.y);
            }

            if (!consumedLeftPress && this.ghostSignalant && !this.isMouseOverUi()) {
                consumedLeftPress = storageUi.placeGhostSignalant(this, this.getMouseWorldPosition());
            }

            if (!consumedLeftPress && !this.isMouseOverUi()) {
                const clickedSignalant = this.getSignalantAtScreenPoint(mouseX, mouseY);
                if (clickedSignalant) {
                    sfx.play("pheromoneAntClicked");
                    if (clickedSignalant === this.activeSignalant) {
                        if (!clickedSignalant.isFixed) {
                            consumedLeftPress = storageUi.replaceCurrentSignalant(this);
                        } else {
                            consumedLeftPress = true;
                        }
                    } else {
                        this.setActiveSignalant(clickedSignalant);
                        consumedLeftPress = true;
                    }
                } else if (this.activeSignalant) {
                    this.setActiveSignalant(null);
                    consumedLeftPress = true;
                }
            }

            if (!consumedLeftPress && this.isMouseOverUi()) {
                consumedLeftPress = true;
            }

            tutorial.handleLeftClick(mouseX, mouseY, { avoidRect: tutorialAvoidRect });
        }

        return {
            allowCameraPan: !this.hasExclusiveSignalantInteraction() && !this.isMouseOverUi() && !consumedLeftPress,
            allowCameraZoom: !consumedWheel,
            allowQueenRightClick: !this.activeSignalant && !consumedRightPress && !this.ghostSignalant && !this.isMouseOverUi(),
            isPheromoneAntMoving,
            isQueenMoving: !this.activeSignalant
                && !consumedRightPress
                && !this.ghostSignalant
                && !this.isMouseOverUi()
                && controls.mouse.buttons.right
                && queenUi.getQueen().active
                && !queenUi.getQueen().isFixed
        };
    }

    draw(ctx) {
        this.reposition();
        const activeStatusSignalant = statusUi.getSignalant(this);
        const tutorialAvoidRect = statusUi.isVisible(activeStatusSignalant) ? statusUi.getPanelRect() : null;

        storageUi.drawGhostSignalant(ctx, cam, this.ghostSignalant, this.getMouseWorldPosition());
        statsUi.draw(ctx);
        queenUi.draw(ctx);
        storageUi.draw(ctx);
        anthillUi.draw(ctx);
        soundUi.draw(ctx);
        tutorial.draw(ctx, { avoidRect: tutorialAvoidRect });
        statusUi.draw(ctx, this);
    }
}

export const ui = new Ui();