local E = select(2, ...) -- Engine
local CO,LOC,UF,AB,LT,AUR,TT = E:LoadModules("Config", "Locale", "Unitframes", "Actionbars", "Layout", "Auras", "Tooltip")

local _
LT.F = CreateFrame("Frame", "LT", E.Parent, "SecureHandlerStateTemplate")
local Location = CreateFrame("Frame", "Location", E.Parent)
local EdgeBottom = CreateFrame("Frame", "EdgeBottom", E.Parent)
local Fps = CreateFrame("Frame", "Fps", E.Parent)
local Ping = CreateFrame("Frame", "Ping", E.Parent)
local LocationInit, LocationFonts, FontInit, DataFonts
local ClassColor, LastPlayerCoordinates
local EDGETILE_BOTTOM_TEXTURE, LOCATION_UPDATE_FREQUENCY, STATICON_TEXTURE, EDGETILE_BOTTOM_TEXTURE_MODERN, LOCATIONPANEL_EDGE_TEXTURE, BAR_TEXTURE, BAR_SMALL_TEXTURE

	STATICON_TEXTURE					= [[Interface\AddOns\CUI\Textures\layout\StatIconOuter]]
	
	LOCATIONPANEL_EDGE_TEXTURE				= [[Interface\AddOns\CUI\Textures\layout\modern\LayoutBarEdge]]
	BAR_TEXTURE								= [[Interface\AddOns\CUI\Textures\layout\modern\LayoutBar]]
	BAR_SMALL_TEXTURE						= [[Interface\AddOns\CUI\Textures\layout\modern\LayoutBarSmall]]
	EDGETILE_BOTTOM_TEXTURE					= [[Interface\AddOns\CUI\Textures\layout\modern\LayoutBottomBarEdge]]
	--EDGETILE_BOTTOM_TEXTURE_MODERN			= [[Interface\AddOns\CUI\Textures\layout\modern\EdgeTileBottomModern]]
	LOCATION_UPDATE_FREQUENCY				= 0.1
	
	LT.F.RangeTimer = 0
	LastPlayerCoordinates = {["x"] = 0, ["y"] = 0}
	DataFonts = {
		["CoordX"] 		= {"Location", "", 13, "LEFT", {80,-2}},
		["CoordY"] 		= {"Location", "", 13, "RIGHT", {-80,-2}},
		["Zone"] 		= {"Location", "", 14, "CENTER", {0,-2}},
		["Fps"] 		= {"EdgeBottom", "Left", 14, "BOTTOMLEFT", {10,10}},
		["Ping"] 		= {"EdgeBottom", "Right", 14, "BOTTOMRIGHT", {-10,10}},
	}

do
	LT.F:SetAttribute("_onstate-visible", [[
		if newstate == 1 then
			self:Show();
		else
			self:Hide();
		end
	]]);
	
	RegisterStateDriver(LT.F, "visible", "[petbattle] 0;1")
end
	
function LT:InitDataPanels()
	local PositionData
	if E:IsLegionClient() then
		PositionData = E.GetPlayerMapPosition("player")
		local x,y = PositionData
	else
		PositionData = E.GetPlayerMapPosition(E.GetCurrentMapID("player") or 0, "player")
		local x,y = PositionData.x, PositionData.y
	end
	
	Location:ClearAllPoints()
	Location:SetPoint("CENTER", E.Parent, "CENTER")
	
	Location.Tex = LT.F:CreateTexture(nil, "BACKGROUND")
	Location.Tex:SetSize(750,30)
	Location.Tex:SetPoint("TOP", E.Parent, "TOP")
	Location.Tex:SetTexture(BAR_TEXTURE)
	Location.Tex:SetBlendMode("BLEND")
	Location.Tex:SetAlpha(1)
	Location.Tex:SetVertexColor(0.8,0.8,0.8)
	
	Location.Tex.Left = LT.F:CreateTexture(nil, "BACKGROUND")
	Location.Tex.Left:SetSize(60,60)
	Location.Tex.Left:SetPoint("TOPLEFT", Location.Tex, "TOPLEFT", -60, 0)
	Location.Tex.Left:SetTexture(LOCATIONPANEL_EDGE_TEXTURE)
	Location.Tex.Left:SetBlendMode("BLEND")
	Location.Tex.Left:SetAlpha(1)
	Location.Tex.Left:SetVertexColor(0.8,0.8,0.8)
	Location.Tex.Left:SetTexCoord(0,1,0,1)
	
	Location.Tex.Right = LT.F:CreateTexture(nil, "BACKGROUND")
	Location.Tex.Right:SetSize(60,60)
	Location.Tex.Right:SetPoint("TOPRIGHT", Location.Tex, "TOPRIGHT", 60, 0)
	Location.Tex.Right:SetTexture(LOCATIONPANEL_EDGE_TEXTURE)
	Location.Tex.Right:SetBlendMode("BLEND")
	Location.Tex.Right:SetAlpha(1)
	Location.Tex.Right:SetVertexColor(0.8,0.8,0.8)
	Location.Tex.Right:SetTexCoord(1,0,0,1)
	
	LT.Location = Location
	
	FontInit = function(Object, Parent, SubParent, FontSize, Point, Offset)
		local Instance = LT[Parent]
		if SubParent ~= "" then
			Instance = LT[Parent][SubParent]
		end
		
		Instance[Object] = LT.F:CreateFontString(nil, "BORDER")
		E:InitializeFontFrame(Instance[Object], "BORDER", CO.Media:Fetch("font", self.db.location["fontType"]), FontSize, {0.8,0.8,0.8}, 1, {0,0}, "", 0, 0, L, Point, {1,1})
		Instance[Object]:SetFont(CO.Media:Fetch("font", self.db.location["fontType"]), FontSize, "")
		Instance[Object]:ClearAllPoints()
		if Parent == "Location" then
			Instance[Object]:SetPoint(Point, Location.Tex, Point, Offset[1], Offset[2])
		elseif Parent == "EdgeBottom" then
			Instance[Object]:SetPoint(Point, Instance, Point, Offset[1], Offset[2])
			if SubParent == "Left" then
				Instance[Object]:SetJustifyH("LEFT")
			else
				Instance[Object]:SetJustifyH("RIGHT")
			end
		end
	end
	for k,v in pairs(DataFonts) do
		FontInit(k, v[1],v[2],v[3],v[4],v[5])
	end
	
	Location:RegisterEvent("ZONE_CHANGED")
	Location:RegisterEvent("ZONE_CHANGED_INDOORS")
	Location:RegisterEvent("ZONE_CHANGED_NEW_AREA")
	Location:SetScript("OnEvent", function(self, event, ...)
		LT:UpdateLocationZone()
	end)
	local RangeTimer = LT.F.RangeTimer
	LT.F:SetScript("OnUpdate", function(self, elapsed)
		RangeTimer = self.RangeTimer;
		if ( RangeTimer ) then
			RangeTimer = RangeTimer - elapsed;

			if ( RangeTimer <= 0 ) then
				LT:UpdateLocationCoords()
				LT:UpdateSystemValues()
				RangeTimer = LOCATION_UPDATE_FREQUENCY;
			end

			self.RangeTimer = RangeTimer;
		end
	end)
	
	LT:UpdateLocationZone()
end

local ColorizedReturn = 0
local ColorizedPing = {[0] = "FF2ded4d", [75] = "FFe3b034", [150] = "FFea2020"}
local ColorizedFPS = {[0] = "FFea2020", [25] = "FFe3b034", [45] = "FF2ded4d"}
function LT:GetColorized(type, value)
	if type == "ping" then
		for k,v in pairs(ColorizedPing) do
			if k <= value then
				ColorizedReturn = "|c" .. v.. value .. "ms" .. "|r"
			end
			-- No else, since we otherwise won't iterate through every case (it's not iterating ordered through tables)
		end
	elseif type == "fps" then
		for k,v in pairs(ColorizedFPS) do
			if k <= value then
				ColorizedReturn = "|c" .. v.. E:Round(value,1) .. "|r"
			end
			-- No else, since we otherwise won't iterate through every case (it's not iterating ordered through tables)
		end
	end
	
	return ColorizedReturn
end

local SystemFPS, SystemPing, SystemDown, SystemUp, SystemLagHome, SystemLagWorld, SystemFPSC, SystemPingC
function LT:UpdateSystemValues()
	
	SystemFPS = LT.EdgeBottom.Left.Fps
	SystemPing = LT.EdgeBottom.Right.Ping
	SystemDown, SystemUp, SystemLagHome, SystemLagWorld = GetNetStats()
	
	SystemFPSC = LT:GetColorized("fps", GetFramerate())
	SystemPingC = LT:GetColorized("ping", SystemLagWorld)
	
	SystemFPS:SetText("FPS: " .. SystemFPSC)
	SystemPing:SetText("Ping: " .. SystemPingC)
end

local LocationPositionData, LocationCoordPosX, LocationCoordPosY
function LT:UpdateLocationCoords()
	if E:IsLegionClient() then
		LocationCoordPosX,LocationCoordPosY = E.GetPlayerMapPosition("player")
	else
		LocationPositionData = E.GetPlayerMapPosition(E.GetCurrentMapID("player") or 0, "player")
		LocationCoordPosX,LocationCoordPosY = LocationPositionData.x, LocationPositionData.y
	end
	
	-- In BfA, this seems to behave differently. Apart from that, some zones still have no coordinate-grid. So this will then default to nil.
	--if position then
	--	posX = position["x"]
	--	posY = position["y"]
	--end
	
	if LocationCoordPosX and LocationCoordPosY then
		if LocationCoordPosX ~= LastPlayerCoordinates["x"] or LocationCoordPosY ~= LastPlayerCoordinates["y"] then
		
			LT.Location.CoordX:SetText(format("%.2f",	LocationCoordPosX*100))
			LT.Location.CoordY:SetText(format("%.2f",	LocationCoordPosY*100))
			
			LastPlayerCoordinates["x"] = LocationCoordPosX
			LastPlayerCoordinates["y"] = LocationCoordPosY
		end
	else
		LT.Location.CoordX:SetText("")
		LT.Location.CoordY:SetText("")
	end
end

function LT:UpdateLocationZone()
	local pvpType, isSubZonePvP, factionName = GetZonePVPInfo();

	if ( pvpType == "sanctuary" ) then
		LT.Location.Zone:SetTextColor(0.41, 0.8, 0.94);
	elseif ( pvpType == "arena" ) then
		LT.Location.Zone:SetTextColor(1.0, 0.1, 0.1);
	elseif ( pvpType == "friendly" ) then
		if (factionName and factionName ~= "") then
			LT.Location.Zone:SetTextColor(0.1, 1.0, 0.1);
		end
		LT.Location.Zone:SetTextColor(0.1, 1.0, 0.1);
	elseif ( pvpType == "hostile" ) then
		if (factionName and factionName ~= "") then
			LT.Location.Zone:SetTextColor(1.0, 0.1, 0.1);
		end
		LT.Location.Zone:SetTextColor(1.0, 0.1, 0.1);
	elseif ( pvpType == "contested" ) then
		LT.Location.Zone:SetTextColor(1.0, 0.7, 0);
	elseif ( pvpType == "combat" ) then
		LT.Location.Zone:SetTextColor(1.0, 0.1, 0.1);
	else
		LT.Location.Zone:SetTextColor(1.0, 0.9294, 0.7607);
	end
	
	self.CurrentZone 	= GetZoneText()
	self.CurrentSubZone = GetSubZoneText()
	
	if self.CurrentZone == self.CurrentSubZone or self.CurrentSubZone == "" then
		LT.Location.Zone:SetText(format("%s",self.CurrentZone))
	else
		LT.Location.Zone:SetText(format("%s, %s",self.CurrentZone, self.CurrentSubZone))
	end
end

function LT:InitWindowEdgeStyle()
	EdgeBottom.Center = EdgeBottom:CreateTexture(nil, "BACKGROUND")
	EdgeBottom.Center:SetTexture(BAR_SMALL_TEXTURE)
	EdgeBottom.Center:SetSize(GetScreenWidth() - (140 * 2) + 1 ,15)
	EdgeBottom.Center:SetPoint("BOTTOM", E.Parent, "BOTTOM")
	EdgeBottom.Center:SetTexCoord(0,1,0,1)
	EdgeBottom.Center:SetBlendMode("BLEND")
	EdgeBottom.Center:SetAlpha(1)

	EdgeBottom.Left = EdgeBottom:CreateTexture(nil, "BACKGROUND")
	EdgeBottom.Left:SetTexture(EDGETILE_BOTTOM_TEXTURE)
	EdgeBottom.Left:SetSize(140,200)
	EdgeBottom.Left:SetPoint("BOTTOMLEFT", E.Parent, "BOTTOMLEFT")
	EdgeBottom.Left:SetTexCoord(0,1,0,1)
	EdgeBottom.Left:SetBlendMode("BLEND")
	EdgeBottom.Left:SetAlpha(1)
	
	EdgeBottom.Right = EdgeBottom:CreateTexture(nil, "BACKGROUND")
	EdgeBottom.Right:SetTexture(EDGETILE_BOTTOM_TEXTURE)
	EdgeBottom.Right:SetSize(140,200)
	EdgeBottom.Right:SetPoint("BOTTOMRIGHT", E.Parent, "BOTTOMRIGHT")
	EdgeBottom.Right:SetTexCoord(1,0,0,1)
	EdgeBottom.Right:SetBlendMode("BLEND")
	EdgeBottom.Right:SetAlpha(1)
	
	EdgeBottom.Center:SetVertexColor(0.8,0.8,0.8)
	EdgeBottom.Left:SetVertexColor(0.8,0.8,0.8)
	EdgeBottom.Right:SetVertexColor(0.8,0.8,0.8)
	
	LT.EdgeBottom = EdgeBottom
end

E.StatColors = {
	["intellect"] = {0.933, 0.952, 0.266},
	["mastery"] = {0.141, 0.403, 0.941},
	["agility"] = {0.933, 0.952, 0.266},
	["leech"] = {0.325, 0.941, 0.141},
	["versatility"] = {0.713, 0.266, 0.952},
	["haste"] = {0.266, 0.701, 0.952},
	["crit"] = {0.941, 0.141, 0.184},
}

-- /run print(select(2, UnitStat("player", 2)))

E.Stats = {
	["mastery"] 		= {function() return GetCombatRating(CR_MASTERY) end, function() return select(1,GetMasteryEffect()) end},
	["agility"] 		= {function() return select(2, UnitStat("player", 2)) end, function() return nil end},
	["leech"] 			= {function() return GetCombatRating(CR_LIFESTEAL) end, function() return GetCombatRatingBonus(CR_LIFESTEAL) end},
	["versatility"] 	= {function() return GetCombatRating(CR_VERSATILITY_DAMAGE_DONE) end, function() return GetCombatRatingBonus(CR_VERSATILITY_DAMAGE_DONE) + GetVersatilityBonus(CR_VERSATILITY_DAMAGE_DONE) end},
	["haste"] 			= {function() return GetCombatRating(CR_HASTE_MELEE) end, function() return GetCombatRatingBonus(CR_HASTE_MELEE) end},
	["crit"] 			= {function() return GetCombatRating(CR_CRIT_MELEE) end, function() return GetSpellCritChance(2) end},
	
}

LT.StatIcons = {}


function E:GetStatValue(Stat)
	return unpack(E.Stats[Stat])
end

function LT:CreateStatIcon(P, S)
	local F = CreateFrame("Frame", "StatIcon"..S, P)
	F:RegisterEvent("PLAYER_EQUIPMENT_CHANGED")
	
	local ValueRaw, Value
	ValueRaw = select(1,E:GetStatValue(S))()
	Value = select(2,E:GetStatValue(S))()
	
	
	
	F.Stat = S
	
	F:SetSize(125,125)
	F:SetPoint("CENTER", P, "CENTER")
	--print(ValueRaw)
	--print(Value)
	local RawYOffset, RawFontSize = -20, 10
	local hasPct = false
	
	local nameCol = {0.952, 0.737, 0.266}
	local col = E.StatColors[S]
	
	F.Overlay = F:CreateTexture(nil, "OVERLAY")
	F.Overlay:SetAllPoints(F)
	F.Overlay:SetTexture(STATICON_TEXTURE)
	F.Overlay:SetBlendMode("ADD")
	F.Overlay:SetVertexColor(col[1],col[2],col[3], 1)
	
	if Value then
		F.Value = F:CreateFontString(nil, "ARTWORK")
		E:InitializeFontFrame(F.Value, "ARTWORK", "FRIZQT__.TTF", 10, {col[1],col[2],col[3]}, 1, {0,0}, "", 125, 30, F, "CENTER", {1,1})
		F.Value:ClearAllPoints()
		F.Value:SetPoint("CENTER", F, 'CENTER', 0, -10)
		F.Value:SetText(E:Round(Value,2) .. "%")
		
		hasPct = true
	end
	
	if not hasPct then
		RawYOffset = -15
		RawFontSize = 11
	end
	
	F.Name = F:CreateFontString(nil, "ARTWORK")
	E:InitializeFontFrame(F.Name, "ARTWORK", "FRIZQT__.TTF", 12, {col[1],col[2],col[3]}, 1, {0,0}, "", 125, 30, F, "CENTER", {1,1})
	F.Name:ClearAllPoints()
	F.Name:SetPoint("CENTER", F, 'CENTER', 0, 30)
	F.Name:SetText(LOC[S])
	
	F.ValueRaw = F:CreateFontString(nil, "ARTWORK")
	E:InitializeFontFrame(F.ValueRaw, "ARTWORK", "FRIZQT__.TTF", RawFontSize, {col[1],col[2],col[3]}, 1, {0,0}, "", 125, 30, F, "CENTER", {1,1})
	F.ValueRaw:ClearAllPoints()
	F.ValueRaw:SetPoint("CENTER", F, 'CENTER', 0, RawYOffset)
	F.ValueRaw:SetText(E:readableNumber(ValueRaw, 2))
	
	-- Updating for once for every frame is probably not the best way...
	-- Let's find another one, yeah?
	F:SetScript("OnEvent", function(self, event, ...)
		LT:UpdateStatIcons()
	end)
	
	-- PaperDollFrame_SetLabelAndText(F, "KRIT", 121, false, 100)
	LT.StatIcons[S] = F
	
	return F
end

function LT:UpdateStatIcons()
	local ValueRaw, Value
	for k,v in pairs(LT.StatIcons) do
		ValueRaw = select(1,E:GetStatValue(v.Stat))()
		Value = select(2,E:GetStatValue(v.Stat))()
		
		if Value then
			v.Value:SetText(E:Round(Value,2) .. "%")
		end
		v.ValueRaw:SetText(E:readableNumber(ValueRaw, 2))
	end
end

local function OnShow_CharacterStatsPane()
	self = CharacterStatsPane
	local kids = { self:GetChildren() }
	CharacterFrame:SetWidth(740)
	
	for _, child in pairs(kids) do
		child:Hide()
	end
	self.ClassBackground:SetWidth(self:GetWidth())
	
	-- Primary Stats
	local Agility = LT:CreateStatIcon(self, "agility")
	Agility:SetPoint("TOPLEFT", self, "TOPLEFT", 0, -10)
	
	-- Secondary Stats
	local Mastery = LT:CreateStatIcon(self, "mastery")
	Mastery:SetPoint("LEFT", self, "LEFT", 0, 0)
	local Versatility = LT:CreateStatIcon(self, "versatility")
	Versatility:SetPoint("LEFT", self, "LEFT", 90, 0)
	local Haste = LT:CreateStatIcon(self, "haste")
	Haste:SetPoint("LEFT", self, "LEFT", 180, 0)
	local Crit = LT:CreateStatIcon(self, "crit")
	Crit:SetPoint("LEFT", self, "LEFT", 270, 0)
	
	-- Tertiary Stats
	local Leech = LT:CreateStatIcon(self, "leech")
	Leech:SetPoint("BOTTOMLEFT", self, "BOTTOMLEFT", 0, 10)
	
	LT:UpdateStatIcons()
end

function LT:StylePaperDoll()
	local RightColumn, PaperDollFrameWidth
	local F = CreateFrame("Frame")
	F:Hide()
	
	PaperDollFrame:HookScript("OnShow", function(self)
		--CharacterStatsPane:Hide()
		RightColumn = CharacterFrameInsetRight
	end)
	
	CharacterStatsPane:HookScript("OnShow", function(self)
		OnShow_CharacterStatsPane()
	end)
	
	PaperDollEquipmentManagerPane:HookScript("OnShow", function(self)
		CharacterFrame:SetWidth(540)
		--[[PaperDollEquipmentManagerPaneScrollChild:SetWidth(self:GetWidth() - 50)
		for i=1,100 do
			local btn = _G["PaperDollEquipmentManagerPaneButton" .. i]
			if not btn then break else
				btn:SetWidth(self:GetWidth() - 35)
				btn.BgMiddle:SetWidth(self:GetWidth() - 35)
				btn.HighlightBar:SetWidth(self:GetWidth() - 35)
			end
		end]]
	end)
	
	hooksecurefunc('PaperDollFrame_UpdateStats', function(...) OnShow_CharacterStatsPane() end)
end

function LT:Init()
	CO = E:GetModule("Config")
	self.db = CO.db.profile.layout
	ClassColor = E:GetUnitClassColor("player")
	
	LT.F:SetPoint("CENTER", E.Parent, "CENTER")
	
	LT:InitWindowEdgeStyle()
	LT:InitDataPanels()
	
	-- Early Design phase style
	-- LT:StylePaperDoll() 
end

E:AddModule("Layout", LT)


-- GameTooltip:SetOwner(self, "ANCHOR_LEFT");
						-- local pvpType, isSubZonePvP, factionName = GetZonePVPInfo();
						-- Minimap_SetTooltip( pvpType, factionName );
-- GameTooltip:Show();