/*
 *   This file is a part of the SteamWar software.
 *
 *   Copyright (C) 2025 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.tntleague.events

import de.steamwar.scoreboard.SWScoreboard
import de.steamwar.tntleague.config.TNTLeagueWorldConfig
import de.steamwar.tntleague.game.TNTLeagueGame
import de.steamwar.tntleague.game.TNTLeagueTeam
import de.steamwar.tntleague.inventory.DealerInventory
import de.steamwar.tntleague.util.TNTLeagueScoreboard
import org.bukkit.GameMode
import org.bukkit.Location
import org.bukkit.entity.EntityType
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
import org.bukkit.event.entity.EntityExplodeEvent
import org.bukkit.event.player.PlayerAttemptPickupItemEvent
import org.bukkit.event.player.PlayerInteractEntityEvent
import org.bukkit.event.player.PlayerJoinEvent
import org.bukkit.event.player.PlayerMoveEvent
import org.bukkit.persistence.PersistentDataType

object IngameListener : Listener {

    @EventHandler
    fun onEntityInteract(e: PlayerInteractEntityEvent) {
        if (e.player.gameMode == GameMode.SPECTATOR) return

        if (e.rightClicked.type == EntityType.WANDERING_TRADER) {
            e.isCancelled = true
            DealerInventory(e.player).open()
        }
    }

    @EventHandler
    fun onExplode(e: EntityExplodeEvent) {
        e.blockList().filter { it.type == TNTLeagueWorldConfig.targetMaterial }
            .groupBy { getTeamByTargetLocation(it.location) }
            .filterKeysNotNull()
            .mapValues { it.value.size }
            .forEach { it.key.damagedBlocks += it.value }
    }

    @EventHandler
    fun onJoin(e: PlayerJoinEvent) {
        SWScoreboard.impl.createScoreboard(e.player, TNTLeagueScoreboard(e.player))
    }

    @EventHandler
    fun onMove(e: PlayerMoveEvent) {
        if (TNTLeagueGame.getTeam(e.player) == null) return
        if (e.to.blockZ >= TNTLeagueWorldConfig.lobby.blockZ && e.to.blockZ <= TNTLeagueWorldConfig.lobby.blockZ + 1) {
            e.isCancelled = true
        }
        if (!TNTLeagueWorldConfig.teamsOnSameLine && e.to.blockX >= TNTLeagueWorldConfig.lobby.blockX && e.to.blockX <= TNTLeagueWorldConfig.lobby.blockX + 1) {
            e.isCancelled = true
        }
    }

    @EventHandler
    fun onPickupCoins(e: PlayerAttemptPickupItemEvent) {
        if (e.item.itemStack.persistentDataContainer.has(DealerInventory.coinKey)) {
            val numberOfCoins = e.item.itemStack.persistentDataContainer[DealerInventory.coinKey, PersistentDataType.INTEGER]
                ?: 0
            TNTLeagueGame.getTeam(e.player)?.coins = (e.item.itemStack.amount * numberOfCoins) + (TNTLeagueGame.getTeam(e.player)?.coins
                ?: 0)

            e.item.itemStack.amount = 0
            e.isCancelled = true
            e.flyAtPlayer = true
        }
    }

    private fun getTeamByTargetLocation(location: Location): TNTLeagueTeam? =
        when (location) {
            in TNTLeagueWorldConfig.redTeam.target -> TNTLeagueGame.redTeam
            in TNTLeagueWorldConfig.blueTeam.target -> TNTLeagueGame.blueTeam
            else -> null
        }

    private fun <K, T> Map<K?, T>.filterKeysNotNull(destination: MutableMap<K, T> = mutableMapOf()): Map<K, T> {
        this.forEach { (t, u) -> if (t != null) destination[t] = u }
        return destination
    }
}