/*
    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 { player_controller, send } from "./main.ts";
import { float, int, Message, PacketC, PlayerID, VoteSubject } from "./protocol.ts";
import { System } from "./system.ts";
import { lerp_exp } from "./util.ts";

const KEY_VOTE_AGREE = "Digit1"
const KEY_VOTE_REJECT = "Digit2"

interface ActiveVote {
    total: int,
    agree: int,
    reject: int,
    initiated_by: PlayerID,
    subject: VoteSubject,
    message: Message,
    initial_timeout: float,
    timeout: float,

    anim_box: float,
    anim_cast: float,
    done: boolean
}

export class SVote extends System {
    active?: ActiveVote

    override tick(dt: number) {
        if (!this.active) return
        const a = this.active
        a.anim_cast *= Math.exp(-dt * 5);
        a.anim_box = lerp_exp(a.anim_box, a.done ? 1.1 : 0, dt * 5)
        a.timeout -= dt
        a.timeout = Math.max(a.timeout, 0)
        if (a.anim_box > 1) delete this.active
    }
    override input(ev: KeyboardEvent, down: boolean): boolean {
        if (down && ev.code == KEY_VOTE_AGREE) send({ type: "cast_vote", player: player_controller.my_id!, agree: true })
        else if (down && ev.code == KEY_VOTE_REJECT) send({ type: "cast_vote", player: player_controller.my_id!, agree: false })
        else return false
        return true
    }
    override draw(ctx: CanvasRenderingContext2D) {
        if (!this.active) return
        const a = this.active
        const w = 300
        const h = 200
        const p = 20

        ctx.save()
        ctx.translate(-w * a.anim_box, 0)
        ctx.translate(p, p)
        let r = 1, g = 1, b = 1
        if (a.anim_cast > 0) { r -= a.anim_cast; b -= a.anim_cast }
        if (a.anim_cast < 0) { g += a.anim_cast; b += a.anim_cast }
        ctx.fillStyle = `rgba(${r * 255}, ${g * 255}, ${b * 255}, 0.67)`
        ctx.fillRect(0, 0, 300, 200)
        ctx.font = "20px sans-serif"
        ctx.fillStyle = "black"
        ctx.fillText(message_str(a.message), p, p + 20, w - p * 2)

        ctx.fillStyle = "#0008"
        ctx.fillRect(0, 0, (1 - a.timeout / a.initial_timeout) * w, 10)

        const bar_height = 50
        ctx.translate(p, h - bar_height - p)
        ctx.scale(w - p * 2, bar_height)
        ctx.fillStyle = "#0008"
        ctx.fillRect(0, 0, 1, 1)
        ctx.fillRect(0.49, 0, 0.02, 1)
        ctx.fillStyle = "#51ff00"
        ctx.fillRect(0, 0, a.agree / a.total, 1)
        ctx.fillStyle = "#ff0000"
        ctx.fillRect(1 - (a.reject / a.total), 0, (a.reject / a.total), 1)
        ctx.restore()

    }
    override packet(p: PacketC): void {
        if (p.type == "vote_started") {
            this.active = {
                agree: 0,
                reject: 0,
                total: 0,
                initiated_by: p.initiated_by,
                message: p.message,
                subject: p.subject,
                anim_box: 1,
                anim_cast: 0,
                done: false,
                initial_timeout: p.timeout,
                timeout: p.timeout
            }
        } else if (p.type == "vote_ended" && this.active) {
            this.active.done = true
        } else if (p.type == "vote_updated" && this.active) {
            const a = this.active;
            if (p.agree > a.agree) a.anim_cast += 1
            if (p.reject > a.reject) a.anim_cast -= 1
            a.agree = p.agree
            a.reject = p.reject
            a.total = p.total
        }
    }
}
