aura_env.me = UnitName("player")
aura_env.reading = false
aura_env.fullMessage = {}
aura_env.displayString = ""
aura_env.messageSent = false
aura_env.previousTarget = ""

---@class ScoreColorer
---@field colors table<number, Color>
---@field breakpoints table<number>
aura_env.ScoreColorer = {
	--- Make sure colors and breakpoints always have the same number of entries! VERY IMPORTANT!
	---@type table<number, Color>
	colors = {
		{ r = 0.62, g = 0.62, b = 0.62 }, -- Grey
		{ r = 1, g = 1, b = 1 }, -- White
		{ r = 0.12, g = 1, b = 0 }, -- Green
		{ r = 0, g = 0.44, b = 0.87 }, -- Blue
		{ r = 0.64, g = 0.21, b = 0.93 }, -- Purple
		{ r = 1, g = 0.5, b = 0 }, -- Orange
		{ r = 1, g = 0.2, b = 0.23 },
		{ r = 0, g = 0.8, b = 1.0 }, -- Blizzard Blue
	},
	breakpoints = { 0, 100, 200, 300, 400, 550, 750, 9999 },

	---@param value number
	---@return Color, nil|string
	Interpolate = function(value)
		local color = { r = 0, g = 0, b = 0 }

		---@type table<number, table<number, number>>
		local bracket = { { 0, 0 }, { 1, 1 } }
		for i = 1, #aura_env.ScoreColorer.breakpoints do
			if value < aura_env.ScoreColorer.breakpoints[i] then
				bracket[2] = { i, aura_env.ScoreColorer.breakpoints[i] }
				break
			end
			bracket[1] = { i, aura_env.ScoreColorer.breakpoints[i] }
		end

		---@type Color
		local startColor = aura_env.ScoreColorer.colors[bracket[1][1]]
		---@type Color
		local endColor = aura_env.ScoreColorer.colors[bracket[2][1]]

		local fraction = (value - bracket[1][2]) / (bracket[2][2] - bracket[1][2])

		for k, v in pairs(startColor) do
			color[k] = aura_env.ScoreColorer.lerp(v, endColor[k], fraction)
		end

		return color, nil
	end,

	---@param a number
	---@param b number
	---@param t number
	---@return number
	lerp = function(a, b, t) return a * (1 - t) + b * t end,
}
---@class KeyLevel
---@field colors table<number, Color>
---@field breakpoints table<number>
aura_env.KeyLevel = {
	--- Make sure colors and breakpoints always have the same number of entries! VERY IMPORTANT!
	---@type table<number, Color>
	colors = {
		{ r = 0.62, g = 0.62, b = 0.62 }, -- Grey
		{ r = 1, g = 1, b = 1 }, -- White
		{ r = 0.12, g = 1, b = 0 }, -- Green
		{ r = 0, g = 0.44, b = 0.87 }, -- Blue
		{ r = 0.64, g = 0.21, b = 0.93 }, -- Purple
		{ r = 1, g = 0.5, b = 0 }, -- Orange
		{ r = 1, g = 0.2, b = 0.23 },
		{ r = 0, g = 0.8, b = 1.0 }, -- Blizzard Blue
	},
	breakpoints = { 1, 10, 15, 20, 25, 29, 33, 9999 },

	---@param value number
	---@return Color, nil|string
	Interpolate = function(value)
		local color = { r = 0, g = 0, b = 0 }

		---@type table<number, table<number, number>>
		local bracket = { { 0, 0 }, { 1, 1 } }
		for i = 1, #aura_env.KeyLevel.breakpoints do
			if value < aura_env.KeyLevel.breakpoints[i] then
				bracket[2] = { i, aura_env.KeyLevel.breakpoints[i] }
				break
			end
			bracket[1] = { i, aura_env.KeyLevel.breakpoints[i] }
		end

		---@type Color
		local startColor = aura_env.KeyLevel.colors[bracket[1][1]]
		---@type Color
		local endColor = aura_env.KeyLevel.colors[bracket[2][1]]

		local fraction = (value - bracket[1][2]) / (bracket[2][2] - bracket[1][2])

		for k, v in pairs(startColor) do
			color[k] = aura_env.KeyLevel.lerp(v, endColor[k], fraction)
		end

		return color, nil
	end,

	---@param a number
	---@param b number
	---@param t number
	---@return number
	lerp = function(a, b, t) return a * (1 - t) + b * t end,
}

---@class Key
---@field name string
---@field role string
---@field level string
---@field time string
---@field score number
Key = {
	---@return Key
	---@param name string
	---@param role string
	---@param level string
	---@param time string
	---@param score string
	new = function(name, role, level, time, score)
		local self = setmetatable({}, {
			__index = Key,
			__tostring = function(self)
				local score = self.score
				local keyLevel = tonumber(self.level:match("%d+$")) or 0

				local formattedScore, err = aura_env.ScoreColorer.Interpolate(self.score)
				if not err then
					score = string.format(
						"|cff%02x%02x%02x%d|r",
						formattedScore.r * 255,
						formattedScore.g * 255,
						formattedScore.b * 255,
						self.score
					)
				end

				local formattedLevel, err = aura_env.KeyLevel.Interpolate(keyLevel)
				if not err then
					level = string.format(
						"|cff%02x%02x%02x%s|r",
						formattedLevel.r * 255,
						formattedLevel.g * 255,
						formattedLevel.b * 255,
						self.level
					)
				end

				return string.format("%-30s %-10s %-10s %-10s %-10s", self.name, self.role, level, self.time, score)
			end,
		})
		self.name = name
		self.role = role
		self.level = level
		self.time = time
		self.score = tonumber(score) or 0
		return self
	end,
	---@return string
	hash = function(self) return table.concat({ self.name, self.role, self.level, self.time, self.score }, "/") end,

	---@param self Key
	---@param other Key
	---@return boolean
	compareTo = function(self, other)
		if not self then return true end
		if not other then return false end
		if self.name <= other.name then return true end
		return false
	end,
	---@param self Key
	register = function(self)
		if not WeakAurasSaved.Cyka then WeakAurasSaved.Cyka = {} end
		if not WeakAurasSaved.Cyka.MData then WeakAurasSaved.Cyka.MData = {} end
		WeakAurasSaved.Cyka.MData[self:hash()] = self
	end,
}

---@param keys Key[]
local function render(keys)
	local str = {}
	for k, v in ipairs(keys) do
		str[#str + 1] = tostring(v)
	end
	aura_env.displayString = table.concat(str, "\n")
end

function aura_env.Process()
	---@type Key[]
	local keys = {}
	for k, msg in ipairs(aura_env.fullMessage) do
		local key, role, level, time, score = string.match(msg, "^->([^/]+)/([^/]+)/([^/]+)/([^/]+)/(.+)$")

		key = string.gsub(key, "^%s+", "")
		key = string.gsub(key, "%s+$", "")
		role = string.gsub(role, "%s+", "")
		level = string.gsub(level, "%s+", "")
		time = string.gsub(time, "%s+", "")
		score = string.gsub(score, "%s+", "")

		local keyObj = Key.new(key, role, level, time, score)
		keyObj:register()
		if key then keys[#keys + 1] = keyObj end
	end
	table.sort(keys, Key.compareTo)
	render(keys)
end

-- /run WeakAurasSaved.Cyka.MData = {}
-- /dump WeakAurasSaved.Cyka.MData
-- /dump InterfaceGUI.Cashe_1[UnitGUID("player")]
