package pw.hamzantal.vagueenchants.enchantments

import hazae41.minecraft.kutils.bukkit.listen
import hazae41.minecraft.kutils.bukkit.msg
import net.minecraft.server.v1_10_R1.BlockPosition
import org.bukkit.Material
import org.bukkit.craftbukkit.v1_10_R1.entity.CraftPlayer
import org.bukkit.entity.Player
import org.bukkit.event.block.BlockBreakEvent
import pw.hamzantal.vagueenchants.*
import pw.hamzantal.vagueenchants.commands.c

class Slicing (id: Int) : CustomEnchant(id, Config.slicing, "SLICING") {

	init {
		VagueEnchants.enchants += this
		val pl = VagueEnchants.pl
		pl.registerEnchantment(this)
		pl.listen(ignoreCancelled = true, callback = this::onBreak)
	}

	private val breaking = mutableListOf<Player>()
	private val cooldowns = hashMapOf<Player, Long>()

	private fun onBreak(e: BlockBreakEvent) {
		val p = e.player
		if (this !in p.inventory.itemInMainHand?.enchantments ?: mapOf() || p in breaking) return
		if (p in cooldowns && cooldowns[p]!! > System.currentTimeMillis()) return
		val level = p.inventory.itemInMainHand.enchantments[this]!!


		val block = e.block
		val loc = block.location
		val item = p.inventory.itemInMainHand
		if (!loc.canMine(p)) return
		val region = loc.validRegion(p)?: return
		cooldowns[p] = System.currentTimeMillis() + 1000 * config.cooldown.x(level).toLong()

		breaking += p
		val maxX  = region.points.maxBy { it.blockX }!!.blockX
		val minX  = region.points.minBy { it.blockX }!!.blockX
		val maxZ  = region.points.maxBy { it.blockZ }!!.blockZ
		val minZ = region.points.minBy { it.blockZ }!!.blockZ
		val pim = (p as CraftPlayer).handle.playerInteractManager

		for (x in minX..maxX) {
			for(z in minZ..maxZ) {
				val newBlk = loc.world.getBlockAt(x, loc.blockY, z)
				if (newBlk.type == Material.AIR) continue

				val nmsData = pim.world.getType(BlockPosition(x, loc.blockY, z))
				val xp = nmsData.block.getExpDrop(pim.world, nmsData, item.enchantments[LOOT_BONUS_BLOCKS] ?: 0)
				p.giveExp(xp)

				ToolUtils.drops(newBlk, item).forEach { i -> p.inventory.addItem(i) }
				newBlk.type = Material.AIR
			}
		}
		breaking -= p
	}

	override fun inspect(p: Player, level: Int) {
		val cost = config.cost.x(level + 1)
		val cd = config.cooldown.x(level)

		p.msg("&7Description: ${config.description}")
		p.msg("&7Current level: $level")
		p.msg("&7Maximum level: $maxLevel")

		if (level < maxLevel) p.msg("&7Next level cost: $cost")
		else p.msg("&7Level maxed")

		p.msg("&7Cooldown between jackhammer: $cd")
		if (p in cooldowns && cooldowns[p]!! > System.currentTimeMillis())
			p.msg("&7Cooldown remaining: ${(cooldowns[p]!! - System.currentTimeMillis()) / 1000} seconds")
	}

	override fun loreString(level: Int): String {
		return "&7JackHammer ${loreLevel(level)}".c
	}
}