/*
 *   This file is a part of the SteamWar software.
 *
 *   Copyright (C) 2026 SteamWar.de-Serverteam
 *
 *   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, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   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/>.
 */

package de.steamwar.kotlin.ui

import de.steamwar.kotlin.KotlinCore
import de.steamwar.kotlin.ui.context.WindowContext
import net.kyori.adventure.text.Component
import org.bukkit.Bukkit
import org.bukkit.entity.Player
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
import org.bukkit.event.inventory.ClickType
import org.bukkit.event.inventory.InventoryClickEvent
import org.bukkit.event.inventory.InventoryCloseEvent
import org.bukkit.event.inventory.InventoryType
import org.bukkit.inventory.Inventory
import org.bukkit.inventory.InventoryHolder
import org.bukkit.inventory.InventoryView

class UIWindow(val player: Player, val render: WindowContext.() -> Unit): InventoryHolder {
    val onClicks = mutableMapOf<Int, (event: InventoryClickEvent) -> Unit>()
    private var updating = false
    lateinit var bukkitInv: Inventory
        private set
    val context by lazy { WindowContext(this) }

    constructor(size: Int, title: String, player: Player, render: WindowContext.() -> Unit): this(player, render) {
        bukkitInv = KotlinCore.plugin.server.createInventory(this, size * 9, Component.translatable(title))
    }

    constructor(type: InventoryType, title: String, player: Player, render: WindowContext.() -> Unit): this(player, render) {
        assert(type != InventoryType.CHEST) { "Chest inventories should use the constructor with size" }
        bukkitInv = KotlinCore.plugin.server.createInventory(this, type, Component.translatable(title))
    }

    fun open() {
        render(context)
        player.openInventory(bukkitInv)
    }

    fun onClose() {
        if (updating) return

        onClicks.clear()
        context.destroy()
    }

    override fun getInventory() = bukkitInv

    companion object : Listener {
        init {
            Bukkit.getPluginManager().registerEvents(this, KotlinCore.plugin)
        }

        @EventHandler
        fun onInventoryClick(event: InventoryClickEvent) {
            val window = event.inventory.holder
            if (window is UIWindow) {
                event.isCancelled = true

                if (window.context.skipDoubleClick && event.click == ClickType.DOUBLE_CLICK) return
                window.onClicks[event.slot]?.invoke(event)
            }
        }

        @EventHandler
        fun onInventoryClose(event: InventoryCloseEvent) {
            val window = event.inventory.holder
            if (window is UIWindow) {
                window.onClose()
            }
        }
    }
}