package pw.hamzantal.mdranks

import me.clip.placeholderapi.expansion.PlaceholderExpansion
import org.bukkit.entity.Player
import pw.hamzantal.mdranks.api.Perms
import pw.hamzantal.mdranks.api.RankType.*
import pw.hamzantal.mdranks.api.Vault
import kotlin.math.min

class PapiExpansion : PlaceholderExpansion() {

	override fun getVersion() = MDRanks.pl.description.version ?: "0.9.0"

	override fun getAuthor() = "hhhapz"

	override fun getIdentifier() = "mdranks"

	override fun persist() = true

	override fun canRegister() = true

	override fun onPlaceholderRequest(p: Player?, params: String?): String {
		if (p == null) return "UNKNOWN_PLAYER"
		if (params == null) return "UNKNOWN_PARAM"
		val args = params.split("_", limit = 2)

		if (args.size == 1) {
			return when (args.component1()) {
				"money"   -> Config.formatC(Vault.balance(p))
				"display" -> {
					val dp = RegularConfig(p, REG)?.display ?: ""
					val pr = PrestigeConfig(p, PRESTIGE)?.display?: Config.defaultPrestige
					val rb = PrestigeConfig(p, REBIRTH)?.display?: Config.defaultRebirth
					return "$rb $pr $dp"
				}
				else      -> "UNKNOWN_PARAM"
			}
		}
		if (params == "display_brackets") {
			val dp = RegularConfig(p, REG)?.display?.wBrackets ?: ""
			val pr = PrestigeConfig(p, PRESTIGE)?.display?.wBrackets
				?: Config.defaultPrestige.wBrackets
			val rb = PrestigeConfig(p, REBIRTH)?.display?.wBrackets
				?: Config.defaultRebirth.wBrackets
			return "$rb $pr $dp"
		}

		return when (args.component1()) {
			"currentrank"  -> return when (args.component2()) {
				"name"                 -> "${Perms.reg(p)}"
				"displayname"          -> RegularConfig(p, REG)?.display ?: ""
				"displayname_brackets" -> RegularConfig(p, REG)?.display?.wBrackets ?: ""
				else                   -> "UNKNOWN_PARAM"
			}

			"rankup"       -> return when (args.component2()) {
				"name"                       -> RegularConfig.next(p, REG) { "$level" }
				"displayname"                -> RegularConfig.next(p, REG) { display }
				"displayname_brackets"       -> RegularConfig.next(p, REG) { display.wBrackets }
				"cost"                       -> RegularConfig.next(p, REG) { "$cost(p)" }
				"cost_formatted"             -> RegularConfig.next(p, REG) { Config.formatC(cost(p)) }
				"percentage"                 -> String.format("%.1f", min(100.0, RegularConfig.nextPcnt(p, REG) * 100.0))
				"percentage_decimal"         -> String.format("%.2f", min(100.0, RegularConfig.nextPcnt(p, REG)))
				"percentage_nolimit"         -> String.format("%.1f", RegularConfig.nextPcnt(p, REG) * 100.0)
				"percentage_decimal_nolimit" -> String.format("%.2f", RegularConfig.nextPcnt(p, REG))
				else                         -> "UNKNOWN_PARAM"
			}

			"prestige"     -> return when (args.component2()) {
				"name"                 -> "${Perms.prestige(p)}"
				"displayname"          -> PrestigeConfig(p, PRESTIGE)?.display ?: Config.defaultPrestige
				"displayname_brackets" -> PrestigeConfig(p, PRESTIGE)?.display?.wBrackets ?: Config.defaultPrestige.wBrackets
				else                   -> "UNKNOWN_PARAM"
			}

			"nextprestige" -> return when (args.component2()) {
				"name"                       -> PrestigeConfig.next(p, PRESTIGE) { "$level" }
				"displayname"                -> PrestigeConfig.next(p, PRESTIGE) { display }
				"displayname_brackets"       -> PrestigeConfig.next(p, PRESTIGE) { display.wBrackets }
				"cost"                       -> PrestigeConfig.next(p, PRESTIGE) { "$cost(p)" }
				"cost_formatted"             -> PrestigeConfig.next(p, PRESTIGE) { Config.formatC(cost(p)) }
				"percentage"                 -> String.format("%.1f", min(100.0, RegularConfig.nextPcnt(p, PRESTIGE) * 100.0))
				"percentage_decimal"         -> String.format("%.2f", min(100.0, RegularConfig.nextPcnt(p, PRESTIGE)))
				"percentage_nolimit"         -> String.format("%.1f", RegularConfig.nextPcnt(p, PRESTIGE) * 100.0)
				"percentage_decimal_nolimit" -> String.format("%.2f", RegularConfig.nextPcnt(p, PRESTIGE))
				else                         -> "UNKNOWN_PARAM"
			}

			"rebirth"      -> return when (args.component2()) {
				"name"                 -> "${Perms.rebirth(p)}"
				"displayname"          -> RebirthConfig(p, REBIRTH)?.display ?: Config.defaultRebirth
				"displayname_brackets" -> RebirthConfig(p, REBIRTH)?.display?.wBrackets ?: Config.defaultRebirth.wBrackets
				else                   -> "UNKNOWN_PARAM"
			}

			"nextrebirth"  -> return when (args.component2()) {
				"name"                       -> RebirthConfig.next(p, REBIRTH) { "$level" }
				"displayname"                -> RebirthConfig.next(p, REBIRTH) { display }
				"displayname_brackets"                -> RebirthConfig.next(p, REBIRTH) { display.wBrackets }
				"cost"                       -> RebirthConfig.next(p, REBIRTH) { "$cost(p)" }
				"cost_formatted"             -> RebirthConfig.next(p, REBIRTH) { Config.formatC(cost(p)) }
				"percentage"                 -> String.format("%.1f", min(100.0, RegularConfig.nextPcnt(p, REBIRTH) * 100.0))
				"percentage_decimal"         -> String.format("%.2f", min(100.0, RegularConfig.nextPcnt(p, REBIRTH)))
				"percentage_nolimit"         -> String.format("%.1f", RegularConfig.nextPcnt(p, REBIRTH) * 100.0)
				"percentage_decimal_nolimit" -> String.format("%.2f", RegularConfig.nextPcnt(p, REBIRTH))
				else                         -> "UNKNOWN_PARAM"
			}

			"money"        -> return when {
				args.component2() == "nonformatted" -> "${Vault.balance(p)}"
				else                                -> "UNKNOWN_PARAM"
			}
			"next"         -> return when (args.component2()) {
				"percentage"         -> String.format("%.1f", min(100.0, nextPercentage(p) * 100.0))
				"percentage_decimal" -> String.format("%.2f", min(1.0, nextPercentage(p)))
				else                 -> "UNKNOWN_PARAM"
			}
			else           -> "UNKNOWN_PARAM"
		}
	}

	fun nextPercentage(p: Player): Double {
		val bal = Vault.balance(p)

		val reg = RegularConfig(p, REG) ?: throw IllegalStateException("The regular rank data was not found for ${p.name}")
		if (!reg.isLast) return bal / RegularConfig(reg.level + 1).cost(p)

		val currentPrestige = PrestigeConfig(p, PRESTIGE)?.level ?: 0
		if (currentPrestige != PrestigeConfig.max()) return bal / PrestigeConfig(currentPrestige + 1).cost(p)

		val currentRebirth = RebirthConfig(p, REBIRTH)?.level ?: 0
		if (currentRebirth != RebirthConfig.max()) return bal / RebirthConfig(currentRebirth + 1).cost(p)
		return 100.0
	}

}