local COMPAT, _, T = select(4, GetBuildInfo()), ...
local L, CLASSIC = T.L, COMPAT < 12e4

local colors = {L"Add Green Relic", L"Add Yellow Relic", L"Add Blue Relic", L"Add Red Relic"}
Relic_KeyBindings, Relic_ShowTooltip, Relic_UnbindCombat = true, true, true -- SVs

local ACTIVATION_OBJECT_IDS, INTROSPECTION_SPELL_IDS, COMBAT_FLAGS_SELF = {[185890]=1, [185944]=2}, {[40055]=1, [40165]=1, [40166]=1, [40167]=1}, 0x511
local REPRISAL_SID = 40065
local Relic_View, Relic_Textures = Relic_View, {"Interface\\Icons\\Spell_Shadow_AntiMagicShell", "Interface\\Icons\\Spell_Holy_Retribution", "Interface\\Icons\\Spell_Fire_BlueFlameRing", "Interface\\Icons\\Spell_Fire_Burnout"}
local Relic_Chain, Relic_DebuffExpire, Relic_ReprisalTally = {}, 0
local Relic_DefaultKeyset = {"G", "Y", "B", "R"}

local GetTotalReprisalDamage = not CLASSIC and function()
	if InCombatLockdown() then
		return nil
	end
	local st = C_DamageMeter.GetCombatSessionSourceFromType(0, 7, UnitGUID("player"))
	for k,v in pairs(st.combatSpells) do
		if v.spellID == REPRISAL_SID then
			return v.totalAmount
		end
	end
	return 0
end
local function Relic_UpdateUI()
	local chainLength, replaySlots = #Relic_Chain, #Relic_View.replay
	for i=1, math.min(chainLength, replaySlots) do
		local b = Relic_View.replay[i]
		b.tex:SetTexture(Relic_Textures[Relic_Chain[i]])
		b.toolHeader, b.toolText = colors[Relic_Chain[i]], L"Left click to remove this.\nRight click to remove up to here."
		b:Show()
	end
	for i=chainLength+1, replaySlots do
		Relic_View.replay[i]:Hide()
	end
end
local function Relic_Shift()
	for i=0,#Relic_Chain do
		Relic_Chain[i] = Relic_Chain[i+1]
	end
	Relic_ReprisalTally = GetTotalReprisalDamage and securecall(GetTotalReprisalDamage)
	Relic_UpdateUI()
end
local function Relic_Unshift()
	table.insert(Relic_Chain, 1, Relic_Chain[0])
	Relic_Chain[0] = nil
	Relic_UpdateUI()
end

local function Relic_RecordClick(self)
	PlaySound(SOUNDKIT.U_CHAT_SCROLL_BUTTON)
	Relic_Chain[#Relic_Chain + 1] = self:GetID()
	Relic_UpdateUI()
end
local function Relic_ReplayClick(self, button)
	PlaySound(SOUNDKIT.U_CHAT_SCROLL_BUTTON)
	if button == "LeftButton" then
		tremove(Relic_Chain, self:GetID())
	elseif button == "RightButton" then
		for i=self:GetID(), #Relic_Chain do
			Relic_Chain[i] = nil
		end
	end
	Relic_UpdateUI()
end

local function Relic_BindKeys(self)
	if InCombatLockdown() then
		if Relic_EnableHotkeys ~= false or self.primedKeys then
			UIErrorsFrame:AddMessage(L"You are in combat - key bindings will update when you're finished.", 1, 0.3, 0)
		end
		self.onLockdownEnd = Relic_BindKeys
	else
		ClearOverrideBindings(self)
		if not self:IsVisible() then
			return
		elseif Relic_EnableHotkeys ~= false then
			local keyset = type(Relic_KeyBindings) == "table" and Relic_KeyBindings or Relic_DefaultKeyset
			for i=1,4 do
				local b, key = Relic_View.set[i], keyset[i]
				if key then
					SetOverrideBindingClick(self, 1, key, b:GetName())
					b.toolText = L("Alternatively, press %s."):format(HIGHLIGHT_FONT_COLOR_CODE .. key .. "|r")
				else
					b.toolText = nil
				end
			end
			self.primedKeys = true
		else
			for i=1,4 do
				local b = Relic_View.set[i]
				b.toolText = nil
			end
		end
	end
end
local function Relic_UnBindKeys(self)
	self.onLockdownEnd = nil
	if InCombatLockdown() and self.primedKeys then
		self.onLockdownEnd = Relic_UnBindKeys
		UIErrorsFrame:AddMessage(L"You are in combat - key bindings will update when you're finished.", 1, 0.3, 0)
	elseif self.primedKeys then
		ClearOverrideBindings(self)
		self.primedKeys = false
		return true
	end
end
local function Relic_OnEvent(self, event, ...)
	if event == "PLAYER_REGEN_DISABLED" and Relic_UnbindCombat then
		ClearOverrideBindings(self)
		self.onLockdownEnd, self.primedKeys = Relic_BindKeys, false
	elseif event == "PLAYER_REGEN_ENABLED" and self.onLockdownEnd then
		self:onLockdownEnd()
		self.onLockdownEnd = nil
	elseif event == "COMBAT_LOG_EVENT_UNFILTERED" then
		local _, ev, _3, _sg, _5, _6, _7, _dg, _9, df, _11, sid = CombatLogGetCurrentEventInfo()
		if ev == "SPELL_DAMAGE" and Relic_Chain[0] and sid == REPRISAL_SID and df == COMBAT_FLAGS_SELF then
			Relic_Unshift()
		end
	elseif event == "DAMAGE_METER_COMBAT_SESSION_UPDATED" and Relic_Chain[0] and Relic_ReprisalTally and not InCombatLockdown() and ... == 7 then
		local re = securecall(GetTotalReprisalDamage)
		if re ~= Relic_ReprisalTally and re and Relic_ReprisalTally then
			Relic_Unshift()
		end
		Relic_ReprisalTally = re
	end
end
local function Relic_OnShow(self)
	self:RegisterEvent("PLAYER_REGEN_DISABLED")
	self:RegisterEvent("PLAYER_REGEN_ENABLED")
	self:RegisterEvent(CLASSIC and "COMBAT_LOG_EVENT_UNFILTERED" or "DAMAGE_METER_COMBAT_SESSION_UPDATED")
	Relic_BindKeys(self)
	self:SetScale(math.min(2.5, math.max(1, tonumber(Relic_Scale) or 1)))
end
local function Relic_OnHide(self)
	self:UnregisterEvent("PLAYER_REGEN_DISABLED")
	self:UnregisterEvent(CLASSIC and "COMBAT_LOG_EVENT_UNFILTERED" or "DAMAGE_METER_COMBAT_SESSION_UPDATED")
	if Relic_UnBindKeys(self) then
		self:UnregisterEvent("PLAYER_REGEN_ENABLED")
	end
end

local function Relic_BuffUpdate(self)
	local time = GetTime()
	if (self.nU or 0) < time and (CLASSIC or not InCombatLockdown()) then
		self.nU = time + 0.1
		local i, d = 1 repeat
			d, i = C_UnitAuras.GetDebuffDataByIndex("player", i), i + 1
			local et = d and INTROSPECTION_SPELL_IDS[d.spellId] and d.expirationTime
			if et then
				if et ~= Relic_DebuffExpire then
					Relic_DebuffExpire = et
					Relic_Shift()
				end
				return
			end
		until not d
	end
end

function T.GetKeyBindings()
	return type(Relic_KeyBindings) == "table" and Relic_KeyBindings or Relic_DefaultKeyset
end
function T.SetKeyBinding(idx, bind)
	if type(Relic_KeyBindings) ~= "table" then
		Relic_KeyBindings = {}
		for i=1,4 do
			Relic_KeyBindings[i] = Relic_DefaultKeyset[i]
		end
	end
	Relic_KeyBindings[idx] = bind
	local a, b = Relic_KeyBindings, Relic_DefaultKeyset
	if a[1] == b[1] and a[2] == b[2] and a[3] == b[3] and a[4] == b[4] then
		Relic_KeyBindings = nil
	end
end
function T.OnSettingChange()
	if Relic_View:IsVisible() then
		Relic_OnShow(Relic_View)
	end
end

for i=2,10 do
	Relic_View.replay[i]:SetPoint("TOPLEFT", Relic_View.replay[i-1], "TOPRIGHT", 2, 0)
end
Relic_View.replay[7]:ClearAllPoints()
Relic_View.replay[7]:SetPoint("TOP", Relic_View.replay[2], "BOTTOM", 12, -4)
Relic_View:SetScript("OnMouseUp", Relic_View.StopMovingOrSizing)
Relic_View:SetScript("OnMouseDown", Relic_View.StartMoving)
for i=1,4 do
	local bo = Relic_View.set[i]
	bo.tex:SetTexture(Relic_Textures[i])
	bo:SetScript("OnClick", Relic_RecordClick)
	bo.toolHeader = colors[i]
end

Relic_View:SetScript("OnShow", Relic_OnShow)
Relic_View:SetScript("OnUpdate", Relic_BuffUpdate)
Relic_View:SetScript("OnHide", Relic_OnHide)
Relic_View:SetScript("OnEvent", Relic_OnEvent)
Relic_View:RegisterEvent("PLAYER_REGEN_DISABLED")
Relic_View:RegisterEvent("PLAYER_REGEN_ENABLED")
Relic_View.title:SetText("Ogri'Lazy")
local function onGossipSelect()
	local guid = UnitGUID("npc")
	guid = (CLASSIC or not issecretvalue(guid)) and guid or nil
	if ACTIVATION_OBJECT_IDS[tonumber(guid and guid:match("^GameObject%-.-%-(%d+)%-%x+$") or 0)] then
		Relic_View:Show()
	end
end
if C_GossipInfo.SelectOption then
	hooksecurefunc(C_GossipInfo, "SelectOption", onGossipSelect)
end
if C_GossipInfo.SelectOptionByIndex then
	hooksecurefunc(C_GossipInfo, "SelectOptionByIndex", onGossipSelect)
end
for _, e in ipairs(Relic_View.replay) do
	e:SetScript("OnClick", Relic_ReplayClick)
	e:RegisterForClicks("LeftButtonUp", "RightButtonUp")
end

SLASH_RELIC1, SLASH_RELIC2, SLASH_RELIC3, SlashCmdList.RELIC = "/ogri", "/relic", "/ol", function(msg)
	if msg == "config" or msg == "conf" then
		T.OpenOgriLazyConfig()
	elseif msg == "version" or msg == "v" then
		print("|cff00a0ffOgri'Lazy|r |cffffffff" .. C_AddOns.GetAddOnMetadata("Ogri'Lazy", "Version") .. "|r")
	elseif Relic_View then
		Relic_View:SetShown(not Relic_View:IsShown())
	end
end