CustomAchiever = LibStub("AceAddon-3.0"):NewAddon("CustomAchiever", "AceConsole-3.0", "AceEvent-3.0", "AceComm-3.0", "AceSerializer-3.0")
local L = LibStub("AceLocale-3.0"):GetLocale("CustomAchiever", true)
local AceGUI = LibStub("AceGUI-3.0")
local ACD = LibStub("AceConfigDialog-3.0")
local XITK = LibStub("XamInsightToolKit")

CustomAchieverGlobal_CommPrefix = "CustomAchiever"

customAchieverFramePool = {}
local customAchieverDressUpModelPool = {}
CustomAchieverGlobal_BetweenObjectsGap = 11

CUSTOMACHIEVER_NUM_LINES = 40
local CUSTOMACHIEVER_LINE_WIDTH = 96

local CUSTOMACHIEVER_COL1_WIDTH = 110 -- + Portrait !
local CUSTOMACHIEVER_COL2_WIDTH = 4*32 + 5
local CUSTOMACHIEVER_COL4_WIDTH = 40
local CUSTOMACHIEVER_ALLCOLS_WIDTH = CUSTOMACHIEVER_COL1_WIDTH -- + Portrait !
	+ CUSTOMACHIEVER_COL2_WIDTH
	+ CUSTOMACHIEVER_COL4_WIDTH

CustAc_Krowi_Loaded = false
function CustomAchiever:OnInitialize()
	-- Called when the addon is loaded
	self:RegisterChatCommand("custac", "CustomAchieverChatCommand")
	self:RegisterComm(CustomAchieverGlobal_CommPrefix, "ReceiveDataFrame_OnEvent")
	self:RegisterEvent("PLAYER_ENTERING_WORLD", function()
		CustAc_CreateOrUpdateCategory("CustomAchiever", nil, "Custom Achiever")
		CustAc_CreateOrUpdateAchievement("CustomAchiever1", "CustomAchiever", 134939,  10, "Bonne installation !", "Intaller Custom Achiever.", "", nil, "frFR")
		CustAc_CreateOrUpdateAchievement("CustomAchiever1", "CustomAchiever",    nil, nil, "Happy move in!", "Install Custom Achiever.",        "", nil,"enUS")
		CustAc_CreateOrUpdateAchievement("CustomAchiever2", "CustomAchiever", 134428,  10, "Un petit pas pour Azeroth...",  "Créer votre premier Haut fait.", "", nil,"frFR")
		CustAc_CreateOrUpdateAchievement("CustomAchiever2", "CustomAchiever",    nil, nil, "One small step for Azeroth...", "Create your first Achievement.", "", nil,"enUS")
		CustAc_CompleteAchievement("CustomAchiever1")
	end)
	self:RegisterEvent("GUILD_ROSTER_UPDATE", "OnGuildRosterUpdate")
	
	CustAc_CreateMinimapButton()
	
	self:RegisterEvent("ADDON_LOADED", function(event, arg)
		if(arg == "Krowi_AchievementFilter") then
			--WATCHED_ADDON = "Overachiever_Tabs" -- Overachiever no longer supported. >> Krowi_AchievementFilter
			CustAc_Krowi_Loaded = true
		end
		if(arg == "Blizzard_AchievementUI") then
			self:UnregisterEvent("ADDON_LOADED")
			CustAc_AchievementFrame_Load()
		end
	end)
	
	-- Chat filter
	ChatFrameUtil.AddMessageEventFilter("CHAT_MSG_CHANNEL", self.ChatFilter)
	ChatFrameUtil.AddMessageEventFilter("CHAT_MSG_GUILD", self.ChatFilter)
	--ChatFrameUtil.AddMessageEventFilter("CHAT_MSG_OFFICER", self.ChatFilter) -- Protected chanel - Kstrings
	ChatFrameUtil.AddMessageEventFilter("CHAT_MSG_PARTY", self.ChatFilter)
	ChatFrameUtil.AddMessageEventFilter("CHAT_MSG_PARTY_LEADER", self.ChatFilter)
	ChatFrameUtil.AddMessageEventFilter("CHAT_MSG_RAID", self.ChatFilter)
	ChatFrameUtil.AddMessageEventFilter("CHAT_MSG_RAID_LEADER", self.ChatFilter)
	ChatFrameUtil.AddMessageEventFilter("CHAT_MSG_RAID_WARNING", self.ChatFilter)
	ChatFrameUtil.AddMessageEventFilter("CHAT_MSG_SAY", self.ChatFilter)
	ChatFrameUtil.AddMessageEventFilter("CHAT_MSG_YELL", self.ChatFilter)
	ChatFrameUtil.AddMessageEventFilter("CHAT_MSG_WHISPER", self.ChatFilter)
	ChatFrameUtil.AddMessageEventFilter("CHAT_MSG_WHISPER_INFORM", self.ChatFilter)
	ChatFrameUtil.AddMessageEventFilter("CHAT_MSG_BN_WHISPER", self.ChatFilter)
	ChatFrameUtil.AddMessageEventFilter("CHAT_MSG_BN_WHISPER_INFORM", self.ChatFilter)
	ChatFrameUtil.AddMessageEventFilter("CHAT_MSG_SYSTEM", self.ChatFilter)
end

local playerNotFoundMsg = string.gsub(ERR_CHAT_PLAYER_NOT_FOUND_S, "%%s", "(.-)")
--local lastPlayerNotFoundMsg = ""
--local lastPlayerNotFoundMsgTime = GetTime()
function CustomAchiever:ChatFilter(event, msg, author, ...)
	if event == "CHAT_MSG_SYSTEM" then
		if string.match(msg, playerNotFoundMsg) then
			--local actualTime = GetTime()
			
			-- Extract the player's name
			local playerName = XITK.addRealm(string.match(msg, playerNotFoundMsg))
			
			if CustomAchieverData["PendingUpdates"][playerName] then --or (lastPlayerNotFoundMsg == msg and actualTime <= lastPlayerNotFoundMsgTime + 1) then
				CustAc_NoAcknowledgmentError(playerName)
				return true
			else
				--lastPlayerNotFoundMsg = msg
				--lastPlayerNotFoundMsgTime = actualTime
				return false
			end
		end
	elseif msg then
		local custacDataIdFoundsInChat = {}
		while true do
			local found = false
			msg, found = string.gsub(msg, "%[CustAc_(.-)_(.-)%]", function(id, name)
				if id and not XITK.isPlayerCharacter(author) then
					custacDataIdFoundsInChat[id] = true
				end
				
				return CustomAchiever_CreateHyperlink(id, name)
			end, 1)
			if found == 0 then break end
		end
		
		if XITK.countTableElements(custacDataIdFoundsInChat) > 0 then
			CustAc_SendCallForAchievementsCategories(custacDataIdFoundsInChat, author)
		end
	end
	return false, msg, author, ...
end

-- Function called when the hyperlink is clicked
local function OnHyperlinkClick(self, link, text, button)
    local linkType, linkData = strsplit(":", link, 2)
	local id, name = strsplit("_", linkData, 2)
    if linkType == "CustAc" then
        if IsShiftKeyDown() then
			-- Insert the link into the chat input field on Shift-click
            ChatEdit_InsertLink("".."[CustAc_" .. id .. "_"..name.."]".."")
        else
			if AchievementFrame_LoadUI then
				if (IsKioskModeEnabled and IsKioskModeEnabled()) then
					return
				end
				if ( not AchievementFrame ) then
					AchievementFrame_LoadUI()
				end
			end
            CustAc_ShowAchievement(id)
        end
    else
        -- If it's not our link, call the old handler
        if self.OriginalHyperlinkClick then
            self:OriginalHyperlinkClick(link, text, button)
        end
    end
end

local function CustAc_ReplaceHyperlinkClick()
	for i = 1, 20 do
		local chatFrame = _G["ChatFrame" .. i]
		if chatFrame and not chatFrame.OriginalHyperlinkClick then
			-- Save the old link click handler
			chatFrame.OriginalHyperlinkClick = chatFrame:GetScript("OnHyperlinkClick")
			chatFrame:SetScript("OnHyperlinkClick", OnHyperlinkClick)
		end
	end
end

function CustomAchiever_CreateHyperlink(id, name)
	CustAc_ReplaceHyperlinkClick()
	local realName = CustAc_getLocaleData(CustomAchieverData["Achievements"][id], "name")
	if realName and realName ~= UNKNOWN then
		name = realName
	end
    return YELLOW_FONT_COLOR_CODE.."|HCustAc:" .. id.."_"..name .. "|h[" .. name .. "]|h"..FONT_COLOR_CODE_CLOSE
end

function CustomAchiever:OnGuildRosterUpdate()
	CustAc_SendCallForUsers()
	self:UnregisterEvent("GUILD_ROSTER_UPDATE")
end

function CustomAchiever:OnEnable()
	-- Called when the addon is enabled
	if not CustomAchieverFrame then
		initCustomAchieverBusinessObjects()
        loadCustomAchieverOptions()

		--NewCustomAchieverFrame
		CustomAchieverFrame = CreateFrame("Frame", "CustomAchieverFrame", UIParent, "CustomAchieverFrameTemplate")
		CustomAchieverTargetTooltip:SetScale(0.8)
		CustomAchieverTargetTooltip:SetParent(CustomAchieverFrame)
		
		if XITK.WoWRetail then
			CustomAchieverFrame.RefreshButton.Icon:SetAtlas("UI-RefreshButton", TextureKitConstants.IgnoreAtlasSize)
		else
			CustomAchieverFrame.RefreshButton.Icon:SetTexture([[Interface\AddOns\]].."CustomAchiever\\art\\ui-refreshbutton")
		end

		CustomAchiever:Print(L["CUSTOMACHIEVER_WELCOME"])
		CustomAchiever:LoadAddonsData()
		
		hooksecurefunc("TargetUnit", CustAc_TargetUnit)
		
		TooltipDataProcessor.AddTooltipPostCall(Enum.TooltipDataType.Unit, CustAc_OnTooltipUnit)
		GameTooltip:HookScript("OnShow", CustAc_CommunitiesMemberOnEnter)
	end
end

function CustAc_CommunitiesMemberOnEnter()
	local mouseFocus = XITK.GetMouseFocus()
	if mouseFocus and mouseFocus["memberInfo"] and mouseFocus["memberInfo"]["clubType"] == 2 and mouseFocus["memberInfo"]["name"] then
		local unitFullName = XITK.addRealm(mouseFocus["memberInfo"]["name"])
		if CustomAchieverData["Users"][unitFullName] then
			GameTooltip:AddDoubleLine("CustomAchiever", CustomAchieverData["Users"][unitFullName], 0, 1, 0, 0, 1, 0)
			GameTooltip:Show()
		end
	end
end

function CustAc_OnTooltipUnit(tooltip, data)
	local unitName, unitId = GameTooltip:GetUnit()
	if XITK.IsPlayerUnitSafe(unitId) then
		local unitFullName = XITK.addRealm(unitName)
		if CustomAchieverData["Users"][unitFullName] then
			tooltip:AddDoubleLine("CustomAchiever", CustomAchieverData["Users"][unitFullName], 0, 1, 0, 0, 1, 0)
		end
	end
end

function CustomAchiever:LoadAddonsData()
	local newCustomAchieverData, optionsDataToMerge
	for i=1, C_AddOns.GetNumAddOns() do
		local name = C_AddOns.GetAddOnInfo(i)
		local data = _G[name.."_CustomAchieverData"]
		if data then
			local dataTime        = data["dataTime"] or time()
			local currentDataTime = CustomAchieverData["dataTime"] or 0
			if dataTime ~= currentDataTime then
				newCustomAchieverData = newCustomAchieverData or CustomAchieverData
				for k,v in pairs(data["Categories"]) do
					local import
					if newCustomAchieverData["Categories"][k] then
						local thisDataTime        = v["dataTime"] or dataTime
						local thisCurrentDataTime = (newCustomAchieverData["Categories"][k] and newCustomAchieverData["Categories"][k]["dataTime"]) or currentDataTime
						if thisDataTime > thisCurrentDataTime then
							import = true
						end
					else
						import = true
					end
					if import then
						newCustomAchieverData["Categories"][k] = v
						if data["AwardedPlayers"] and data["AwardedPlayers"][k]           then newCustomAchieverData["AwardedPlayers"][k]      = data["AwardedPlayers"][k] end
						if data["PersonnalCategories"] and data["PersonnalCategories"][k] then newCustomAchieverData["PersonnalCategories"][k] = data["PersonnalCategories"][k] end
					end
				end
				
				for k,v in pairs(data["Achievements"]) do
					local import
					if newCustomAchieverData["Achievements"][k] then
						local thisDataTime        = v["dataTime"] or dataTime
						local thisCurrentDataTime = (newCustomAchieverData["Achievements"][k] and newCustomAchieverData["Achievements"][k]["dataTime"]) or currentDataTime
						if thisDataTime > thisCurrentDataTime then
							import = true
						end
					else
						import = true
					end
					if import then
						newCustomAchieverData["Achievements"][k] = v
						if data["AwardedPlayers"] and data["AwardedPlayers"][k] then newCustomAchieverData["AwardedPlayers"][k] = data["AwardedPlayers"][k] end
					end
				end

				if data["Users"] then
					for k,v in pairs(data["Users"]) do
						if not newCustomAchieverData["Users"][k] then
							newCustomAchieverData["Users"][k] = v
						end
					end
				end
			end
			
			_G[name.."_CustomAchieverData"] = nil
		end
	end
	if newCustomAchieverData then
		CustomAchieverData = newCustomAchieverData
		CustAc_LoadAchievementsData("CustAc_CreateOrUpdateAchievement")
		CustAc_RefreshCustomAchiementFrame()
	end
end

function showIconSelector()
	if not MacroFrame then
		MacroFrame_LoadUI()
	end
	if not CustAc_IconsPopupFrame then
		CustAc_IconsPopupFrame = CreateFrame("Frame", "CustAc_IconsPopupFrame", CustomAchieverFrame, "CustAc_IconsPopupFrameTemplate")
		--CustAc_IconsPopupFrame.BorderBox.EditBoxHeaderText:SetText("tmp")
		CustAc_IconsPopupFrame.BorderBox.IconSelectorEditBox:SetMaxLetters(30) 
		CustAc_IconsPopupFrame.BorderBox.OkayButton:SetScript("OnClick", function()
			PlaySound(SOUNDKIT.GS_TITLE_OPTION_OK)
			CustAc_IconsPopupFrame_OkayButton_OnClick(self)
		end)
		CustAc_IconsPopupFrame.BorderBox.IconSelectorEditBox:SetScript("OnEnterPressed", function()
			PlaySound(SOUNDKIT.GS_TITLE_OPTION_OK)
			CustAc_IconsPopupFrame_OkayButton_OnClick(self)
		end)
	end
	CustAc_IconsPopupFrame:Show()
end

function applyCustomAchieverWindowOptions()--withSummaryFrame)
	retOK, ret = pcall(callbackCustomAchieverWindow, CustomAchieverFrame)
end

function callbackCustomAchieverWindow(aFrame)
	if CustomAchieverOptionsData and CustomAchieverOptionsData["CustomAchieverWindow"] and CustomAchieverOptionsData["CustomAchieverWindow"]["point"] then
		aFrame:ClearAllPoints()
		aFrame:SetPoint(CustomAchieverOptionsData["CustomAchieverWindow"]["point"], UIParent,
			CustomAchieverOptionsData["CustomAchieverWindow"]["relativePoint"], CustomAchieverOptionsData["CustomAchieverWindow"]["xOffset"], CustomAchieverOptionsData["CustomAchieverWindow"]["yOffset"])
	end
end

function customAchieverSaveWindowPosition()
	if CustomAchieverFrame then
		local point, _, relativePoint, xOffset, yOffset = CustomAchieverFrame:GetPoint()
		CustomAchieverOptionsData["CustomAchieverWindow"]["point"] = point
		CustomAchieverOptionsData["CustomAchieverWindow"]["relativePoint"] = relativePoint
		CustomAchieverOptionsData["CustomAchieverWindow"]["xOffset"] = xOffset
		CustomAchieverOptionsData["CustomAchieverWindow"]["yOffset"] = yOffset
	end
	--CustAc_saveCustomAchieverOptionsDataForAddon()
end

function CustomAchiever:ReloadData()
	CustomAchieverBetButton:Hide()
	local numGroupMembers = GetNumGroupMembers()
	if numGroupMembers <= 1 then
		playerJoinsCustomAchieverSession("CustomAchieverSession_"..XITK.playerCharacter(), true, true)
	end
	generateCustomAchieverTable()
end

function CustomAchiever:CustomAchieverChatCommand(input)
	if input == "options" then
		CustomAchiever_OpenOptions()
	else
		CustomAchieverFrame:Show()
	end
end

function CustomAchiever_CompartmentFunc(addon, clickButton)
	if clickButton == "RightButton" then
		CustomAchiever_OpenOptions()
	else
		CustomAchiever_ToggleFrame()
	end
end

function CustomAchiever_CompartmentFuncOnEnter(addon, button)
	local tooltip = "Custom Achiever"
	local tooltipDetail = L["MINIMAP_TOOLTIP1"]
	local tooltipDetail2 = L["MINIMAP_TOOLTIP2"]
	
	button:SetAttribute("tooltip", tooltip)
	button:SetAttribute("tooltipDetail", { tooltipDetail, tooltipDetail2 })
	CustomAchieverButtonEnter(button, nil, "LEFT")
end

function CustomAchiever_CompartmentFuncOnLeave()
	CustomAchieverTooltip:Hide()
end

function CustomAchiever_ToggleFrame()
	if CustomAchieverFrame:IsShown() then
		CustomAchieverFrame:Hide()
	else
		CustomAchieverFrame:Show()
	end
end

function CustomAchiever_OpenOptions()
	ACD:Open("CustomAchiever")
end
