/*
    Hurry Curry! - a game about cooking
    Copyright (C) 2026 Hurry Curry! Contributors

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, version 3 of the License only.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.

*/

import { message_str } from "../locale.ts";
import { camera } from "../main.ts";
import { float, Message, MessageTimeout } from "../protocol.ts";
import { lerp_exp, V2 } from "../util.ts";
import { SSprites } from "./sprites.ts";

const MESSAGE_BG: { [key in MessageStyle]: string } = { normal: "#fff", hint: "#111", error: "#fff", pinned: "rgb(4, 32, 0)" }
const MESSAGE_FG: { [key in MessageStyle]: string } = { normal: "#000", hint: "#fff", error: "#a00", pinned: "#000" }

export type MessageStyle = "hint" | "normal" | "error" | "pinned"

export class MessageRenderer {
    constructor(
        public style: MessageStyle,
        public inner: Message,
        public anim_position: V2,
        public anim_size: number,
        public timeout?: MessageTimeout,
    ) { }

    tick(dt: float): boolean {
        this.anim_size = lerp_exp(this.anim_size, this.timeout ? this.timeout.remaining > 0.3 ? 1 : 0 : 1, dt * 8)
        if (!this.timeout) return false
        this.timeout.remaining -= dt;
        return this.timeout.remaining <= 0
    }
    draw(ctx: CanvasRenderingContext2D, sprites?: SSprites, world?: boolean) {
        ctx.save()
        ctx.translate(this.anim_position.x, this.anim_position.y)
        const scale = Math.min(this.anim_size, 1 - camera.overlay_vis_anim);
        ctx.scale(scale, scale)
        if ("item" in this.inner) {
            ctx.fillStyle = MESSAGE_BG[this.style]
            if (this.style == "pinned") {
                ctx.translate(0, 1)
                ctx.beginPath()
                ctx.arc(0, -1, 0.5, 0, Math.PI * 2)
                ctx.fill()
            } else {
                ctx.beginPath()
                ctx.moveTo(0, -0.3)
                ctx.arc(0, -1, 0.5, Math.PI / 4, Math.PI - Math.PI / 4, true)
                ctx.closePath()
                ctx.fill()
            }

            if (this.timeout) {
                const t = this.timeout.remaining / this.timeout.initial;
                ctx.beginPath()
                ctx.strokeStyle = `hsl(${Math.sqrt(t) * 0.3}turn, 100%, 50%)`
                ctx.lineWidth = 0.1
                ctx.arc(0, -1, 0.45, -Math.PI / 2, -Math.PI / 2 + Math.PI * 2 * (1 - t))
                ctx.stroke()
            }

            ctx.translate(0, -1)
            ctx.save()
            sprites?.draw_item(ctx, this.inner.item)
            ctx.restore()
            ctx.translate(0, 1)
        }
        if ("text" in this.inner || "translation" in this.inner) {
            ctx.translate(0, -1)

            ctx.textAlign = "center"
            ctx.font = "15px " + (world ? "sans-serif" : "monospace")
            if (world) ctx.scale(2 / camera.scale, 2 / camera.scale)

            const lines = message_str(this.inner).split("\n")
            const w = lines.reduce((a, v) => Math.max(a, ctx.measureText(v).width), 0) + 10

            if (world) ctx.translate(0, -lines.length * 15 / 2)

            ctx.fillStyle = MESSAGE_BG[this.style]
            ctx.beginPath()
            ctx.roundRect(-w / 2, -5, w, lines.length * 15 + 10, 5)
            ctx.fill()

            ctx.fillStyle = MESSAGE_FG[this.style]
            ctx.textAlign = "left"
            ctx.textBaseline = "top"
            for (let i = 0; i < lines.length; i++)
                ctx.fillText(lines[i], -w / 2 + 5, i * 15)

            ctx.translate(0, 1)
        }
        ctx.restore()
    }
}
