local E = select(2, ...) -- Engine
local CO, L, TT = E:LoadModules("Config", "Locale", "Tooltip")

--[[-------------------------------------------------------------------------

	We are caching globals, since making those functions local,
	results in a slight performance boost and therefore
	in less CPU time. Exactly what we are aiming for.

-------------------------------------------------------------------------]]--
local _
local GameTooltip_SetDefaultAnchor 	= GameTooltip_SetDefaultAnchor
local GetCreatureDifficultyColor 	= GetCreatureDifficultyColor
local UnitFactionGroup 				= UnitFactionGroup
local UnitName 						= UnitName
local UnitLevel 					= UnitLevel
local UnitClass 					= UnitClass
local UnitRace 						= UnitRace
local GetGuildInfo 					= GetGuildInfo
local UnitHealth 					= UnitHealth
local format						= string.format
-----------------------------------------------------------------------------

TT.CurrentTooltipAnchor = nil
local TooltipAnchor = {
	["TooltipAnchor"]			= {1, 1, -100, 200, "BOTTOMRIGHT"} --SizeX,SizeY,OffsetX,OffsetY
}

TT.FactionColors = {
	ALLIANCE 	= {100, 149, 237},
	HORDE 		= {178, 34, 34},
}
TT.HexFactionColors = {
	ALLIANCE 	= E:rgbToHex(TT.FactionColors.ALLIANCE),
	HORDE 		= E:rgbToHex(TT.FactionColors.HORDE),
}

function TT:SetupHandlers()
	GameTooltip:HookScript("OnTooltipSetUnit", function(self) TT:UpdateUnitTooltip(self) end)
	GameTooltip:HookScript("OnTooltipSetItem", function(self) TT:UpdateItemTooltip(self) end)
	GameTooltip:HookScript("OnTooltipSetQuest", function(self) TT:UpdateQuestTooltip(self) end)
	GameTooltip:HookScript("OnTooltipSetSpell", function(self) TT:UpdateSpellTooltip(self) end)
	-- GameTooltip:HookScript("OnShow", function(self) TT:UpdateStyle() end)

	-- hooksecurefunc("SetCVar", print) -- To find out what CVars there are
end

function TT:GetLevelLine(tt, offset)
	for i=offset, tt:NumLines() do
		self.levelLineTipText = _G["GameTooltipTextLeft"..i]
		if(self.levelLineTipText:GetText() and self.levelLineTipText:GetText():find(LEVEL)) then
			return self.levelLineTipText
		end
	end
end

function TT:UpdateSpellTooltip()

	-- When there is no owner name, the tooltip is most likely supposed to be positioned at a fixed position. We shouldn't mess with that.
	if not GameTooltip:GetOwner():GetName() then return end
	
	GameTooltip:SetPoint("BOTTOMRIGHT", TT.CurrentTooltipAnchor, "BOTTOMRIGHT", 0, 0)
	
	local name, rank, spellID = GameTooltip:GetSpell()
	if not name then return end
	
	local r, g, b = GameTooltip:GetBackdropColor()
	GameTooltip:SetBackdrop( { 
	  bgFile = TT.db.background["backgroundFile"], 
	  edgeFile = "", tile = false, tileSize = 0, edgeSize = 0, 
	  insets = { left = 0, right = 0, top = 0, bottom = 0 }
	});
	GameTooltip:SetBackdropColor(r, g, b, TT.db.background["alpha"])
	GameTooltipText:SetFont(CO.Media:Fetch("font", TT.db.header["fontType"]), TT.db.body["fontSize"], "")
end

function TT:UpdateUnitTooltip(object)

	GameTooltip:SetPoint("BOTTOMRIGHT", TT.CurrentTooltipAnchor, "BOTTOMRIGHT", 0, 0)
	
	self.name, self.unit = GameTooltip:GetUnit()
	if not self.unit then return end
	
	self.targetUnit = self.unit .. "target"
	self.name, self.realm = UnitName(self.unit)
	
	self.TooltipUnitReactionColor  = E:GetUnitReactionColor(self.unit)
	self.TooltipUnitReactionHex = E:rgbToHex({self.TooltipUnitReactionColor.r, self.TooltipUnitReactionColor.g, self.TooltipUnitReactionColor.b}, true)
	if not self.realm then self.realm = "" end
	if UnitIsUnit(self.unit, "player") then
		-- if UnitIsPlayer(self.unit) then self.realm = select(2, UnitFullName(self.unit)) or "" end
	end
	
	if self.realm and self.realm ~= "" then self.realm = format(" - %s", self.realm) end
	
	GameTooltipTextLeft1:SetFont(CO.Media:Fetch("font", TT.db.header["fontType"]), TT.db.header["fontSize"], "")
	
	-- Prevent random Lua-errors
	if self.name and self.realm then
		GameTooltipTextLeft1:SetFormattedText("|c%s%s%s|r", self.TooltipUnitReactionHex, self.name, self.realm)
	end
	
	-- Colorize Race and Class
	if UnitIsPlayer(self.unit) then
		
		self.localeClass, self.class = UnitClass(self.unit)
		self.guildName, self.guildRankName, _, self.guildRealm = GetGuildInfo(self.unit)
		self.race, self.englishRace = UnitRace(self.unit)
		self.level = UnitLevel(self.unit)
		_, self.factionGroup = UnitFactionGroup(self.unit)
		
		self.classColor = CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[self.class] or RAID_CLASS_COLORS[self.class]
		
		self.lineOffset = 2
		if self.guildName then
			self.guildLine = GameTooltipTextLeft2
			
			if self.guildRealm then
				self.guildLine:SetFormattedText("|c%s<%s - %s>|r [%s]", TT.HexFactionColors.ALLIANCE, self.guildName, self.guildRealm, self.guildRankName)
			else
				self.guildLine:SetFormattedText("|c%s<%s>|r [%s]", TT.HexFactionColors.ALLIANCE, self.guildName, self.guildRankName)
			end
			
			self.lineOffset = 3
		end
		
		
		self.levelLine = self:GetLevelLine(object, self.lineOffset)
		if(self.levelLine) then
			self.diffColor = GetCreatureDifficultyColor(UnitLevel(self.unit))
			if(self.factionGroup and englishRace == "Pandaren") then
				self.race = self.factionGroup.." "..self.race
			end
			self.levelLine:SetFormattedText("%s |cff%02x%02x%02x%s|r - |c%s%s, %s|r (%s)", LEVEL, self.diffColor.r * 255, self.diffColor.g * 255, self.diffColor.b * 255, self.level > 0 and self.level or "??", self.classColor.colorStr, self.race or '', self.localeClass, PLAYER)
			
			-- Color faction
			self.factionLine = _G["GameTooltipTextLeft" .. self.lineOffset + 1]
			-- Add faction
			if self.factionLine:GetText() == FACTION_ALLIANCE or self.factionLine:GetText() == FACTION_HORDE then
				if self.factionGroup == FACTION_HORDE then
					self.factionColor = TT.HexFactionColors.HORDE
					self.factionLine:SetFormattedText("|c%s%s|r", self.factionColor, FACTION_HORDE)
				elseif self.factionGroup == FACTION_ALLIANCE then
					self.factionColor = TT.HexFactionColors.ALLIANCE
					self.factionLine:SetFormattedText("|c%s%s|r", self.factionColor, FACTION_ALLIANCE)
				end
			else
				if self.factionGroup == FACTION_HORDE then
					self.factionColor = TT.HexFactionColors.HORDE
					GameTooltip:AddLine(string.format("|c%s%s|r", self.factionColor, FACTION_HORDE))
				elseif self.factionGroup == FACTION_ALLIANCE then
					self.factionColor = TT.HexFactionColors.ALLIANCE
					GameTooltip:AddLine(string.format("|c%s%s|r", self.factionColor, FACTION_ALLIANCE))
				end
			end
		end
	end
	
	TT:SetTooltipTarget(self)
	
	self.backdropR, self.backdropG, self.backdropB = GameTooltip:GetBackdropColor()
	GameTooltip:SetBackdrop( { 
	  bgFile = TT.db.background["backgroundFile"], 
	  edgeFile = "", tile = false, tileSize = 0, edgeSize = 0, 
	  insets = { left = 0, right = 0, top = 0, bottom = 0 }
	});
	GameTooltip:SetBackdropColor(self.backdropR, self.backdropG, self.backdropB, TT.db.background["alpha"])
	GameTooltipText:SetFont(CO.Media:Fetch("font", TT.db.body["fontType"]), TT.db.body["fontSize"], "")
	
	GameTooltipStatusBar:SetStatusBarTexture(CO.db.profile.unitframe.units.all.barTexturePath)
	GameTooltipStatusBar.text:SetText(E:readableNumber(UnitHealth(self.unit), 2) .. " / " .. E:readableNumber(UnitHealthMax(self.unit), 2))
end

function TT:SetTooltipTarget(object)
	object.GroupTargetText = ""
	object.GroupTargetTextEntries = 0
	object.GroupTargetTextNewLine = true -- Control variable for new lines

	if UnitExists(object.unit .. "target") then
		object.targetReactionColor = E:GetUnitReactionColor(object.targetUnit)
		object.targetColor = E:rgbToHex({object.targetReactionColor.r, object.targetReactionColor.g, object.targetReactionColor.b}, true)
		GameTooltip:AddLine(format("<%s: %s>", TARGET, format("|c%s%s|r", object.targetColor, UnitName(object.targetUnit))))
	end
	if not IsInRaid() then
		if IsInGroup() then
			
			for i=1,4 do
				if UnitExists(format("party%starget", i)) and UnitIsUnit(object.unit, format("party%starget", i)) then
					if object.GroupTargetText == "" then
						object.GroupTargetText = UnitName(format("party%s", i))
					else
						if not object.GroupTargetTextNewLine then
							object.GroupTargetText = format("%s, %s", object.GroupTargetText, UnitName(format("party%s", i)))
						else
							object.GroupTargetText = format("%s%s", object.GroupTargetText, UnitName(format("party%s", i)))
						end
					end
					
					object.GroupTargetTextEntries = object.GroupTargetTextEntries + 1
					
					if object.GroupTargetTextEntries % 4 < 1 then
						object.GroupTargetText = object.GroupTargetText .. "\n"
						object.GroupTargetTextNewLine = true
					else
						object.GroupTargetTextNewLine = nil
					end
				end
			end
		end
	else
		for i=1,40 do
			if UnitExists(format("raid%starget", i)) and UnitIsUnit(object.unit, format("raid%starget", i)) then
				if object.GroupTargetText == "" then
					object.GroupTargetText = UnitName(format("raid%s", i))
				else
					--object.GroupTargetText = format("%s, %s", object.GroupTargetText, UnitName(format("raid%s", i)))
					if not object.GroupTargetTextNewLine then
						object.GroupTargetText = format("%s, %s", object.GroupTargetText, UnitName(format("raid%s", i)))
					else
						object.GroupTargetText = format("%s%s", object.GroupTargetText, UnitName(format("raid%s", i)))
					end
				end
				
				object.GroupTargetTextEntries = object.GroupTargetTextEntries + 1
				
				if object.GroupTargetTextEntries % 4 < 1 then
					object.GroupTargetText = object.GroupTargetText .. "\n"
					object.GroupTargetTextNewLine = true
				else
					object.GroupTargetTextNewLine = nil
				end
			end
		end
	end
	
	if object.GroupTargetText ~= "" then
		GameTooltip:AddLine(format("<%s %s> %s", TARGET, L["of"], object.GroupTargetText))
	end
end

function TT:UpdateItemTooltip()

	GameTooltip:SetPoint("BOTTOMRIGHT", TT.CurrentTooltipAnchor, "BOTTOMRIGHT", 0, 0)
	
	local name, link = GameTooltip:GetItem()
	if not name then return end
	
	local r, g, b = GameTooltip:GetBackdropColor()
	GameTooltip:SetBackdrop( { 
	  bgFile = TT.db.background["backgroundFile"], 
	  edgeFile = "", tile = false, tileSize = 0, edgeSize = 0, 
	  insets = { left = 0, right = 0, top = 0, bottom = 0 }
	});
	GameTooltip:SetBackdropColor(r, g, b, TT.db.background["alpha"])
	GameTooltipText:SetFont(CO.Media:Fetch("font", TT.db.header["fontType"]), TT.db.body["fontSize"], "")
end

function TT:UpdateQuestTooltip()

	GameTooltip:SetPoint("BOTTOMRIGHT", TT.CurrentTooltipAnchor, "BOTTOMRIGHT", 0, 0)
	
	local r, g, b = GameTooltip:GetBackdropColor()
	GameTooltip:SetBackdrop( { 
	  bgFile = TT.db.background["backgroundFile"], 
	  edgeFile = "", tile = false, tileSize = 0, edgeSize = 0, 
	  insets = { left = 0, right = 0, top = 0, bottom = 0 }
	});
	GameTooltip:SetBackdropColor(r, g, b, TT.db.background["alpha"])
	GameTooltipText:SetFont(CO.Media:Fetch("font", TT.db.header["fontType"]), TT.db.body["fontSize"], "")
end

-- Updates for not spcified tooltip type
function TT:UpdateStyle()
	GameTooltip:SetPoint("BOTTOMRIGHT", TT.CurrentTooltipAnchor, "BOTTOMRIGHT", 0, 0)
	
	local r, g, b = GameTooltip:GetBackdropColor()
	GameTooltip:SetBackdrop( { 
	  bgFile = TT.db.background["backgroundFile"], 
	  edgeFile = "", tile = false, tileSize = 0, edgeSize = 0, 
	  insets = { left = 0, right = 0, top = 0, bottom = 0 }
	});
	GameTooltip:SetBackdropColor(r, g, b, TT.db.background["alpha"])
	GameTooltipText:SetFont(CO.Media:Fetch("font", TT.db.header["fontType"]), TT.db.body["fontSize"], "")
end

function TT:SetupAnchor()
	
	local Frame

	for k,v in pairs(TooltipAnchor) do
		Frame = E:NewFrame("Frame", k, "MEDIUM", v[1], v[2], _, E.Parent)
		Frame:SetSize(100,50)
		Frame:SetPoint(v[5], E.Parent, v[5])
		E:MoveFrame(Frame, v[3], v[4])
	end
	
	TT.CurrentTooltipAnchor = Frame
	GameTooltip_SetDefaultAnchor(GameTooltip, Frame)
	
	E:CreateMover(Frame, L["tooltipAnchor"])
end

function TT:Init()
	CO = E:GetModule("Config")
	TT.db = CO.db.profile.tooltip
	
	TT:SetupAnchor()
	TT:SetupHandlers()
end

E:AddModule("Tooltip", TT)