local addonName, addon = ...

addon:RegisterDefaultSetting("hudShow", true)
addon:RegisterDefaultSetting("hudWidth", 100)
addon:RegisterDefaultSetting("hudHeight", 100)
addon:RegisterDefaultSetting("hudScale", 1)

local GHudMain = CreateFrame("Frame", "GHudMain", UIParent)

GHudMain:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
GHudMain:SetHeight(3)
GHudMain:SetWidth(3)

GHudMain:RegisterEvent("PLAYER_TARGET_CHANGED")
GHudMain:RegisterEvent("PLAYER_REGEN_ENABLED") 
GHudMain:RegisterEvent("PLAYER_REGEN_DISABLED")
GHudMain:RegisterEvent("UNIT_HEALTH", "player")
GHudMain:RegisterEvent("UNIT_POWER", "player")
GHudMain:RegisterEvent("PLAYER_REGEN_ENABLED")
GHudMain:RegisterEvent("UNIT_PET", "player")

GHudMain:SetScript("OnEvent", function()
	addon:SetHudBackgrounds()
	addon:SetHudAlpha()
end)

function addon:SetupGHud()
	if addon.settings.hudShow then 
		GHudMain:Show()
	else
		GHudMain:Hide()
	end
end

function addon:GHudScale()
	GHudMain:SetScale(addon.settings.hudScale)
end

--[[-----------------------------------------------------------------------------
The IMPORTANT PART! Bar fill function, dont f with this.
-------------------------------------------------------------------------------]]
--bar = texture/frame to alter, required!
--val1, val2 = Upper and lower values for the bar to be drawn (default 0)
--flipH, flipV = Boolean true/false, flips texture horizontally/vertically if true (default false)
--cropx1, cropx2, cropy1, cropy2 = Crop values, swapping high and low values within the xy pairs will not affect flipping (default 0, 1, 0, 1)
function addon:SetBarValue(bar,val1,val2,flipH,flipV,cropx1,cropx2,cropy1,cropy2)
	--Keep the values within a 0-1 range
	val1=math.min(math.max(val1 or 0,0),1);
	val2=math.min(math.max(val2 or 0,0),1);
	
	--Sometimes textures glitch when trying to set a width or height of 0, so handle it here
	if val1==val2 then
		bar:Hide();
		return;
	else
		bar:Show();
	end

	--Texture crop/padding
	cropx1=math.min(math.max(cropx1 or 0,0),1);
	cropx2=math.min(math.max(cropx2 or 1,0),1);
	cropy1=math.min(math.max(cropy1 or 0,0),1);
	cropy2=math.min(math.max(cropy2 or 1,0),1);

	--Set our low and high values
	local low,high=math.min(val1,val2),math.max(val1,val2);

	--Find our parent width and height
	local parent=bar:GetParent();
	local pw,ph=parent:GetWidth(),parent:GetHeight();
	
	--Get our point set, we'll use this to get our bar orientation
	local point=bar:GetPoint(1);
	if not point then return; end-- Handle if point isn't set, perhaps cleared?
	
	--These are our temp origin variables (note one of these pairs can have both vars nil, just use default texcoords for those)
	local origL=point:find("LEFT$");
	local origR=point:find("RIGHT$");
	local origT=point:find("^TOP");
	local origB=point:find("^BOTTOM");

	--Reset point
	bar:SetPoint(point
		,(origL or origR) and (origL and low*pw or -low*pw) or 0--  X offset
		,(origT or origB) and (origB and low*ph or -low*ph) or 0--  Y offset
	);
	--Texcoord calc
	local l,r,t,b=0,1,0,1;--    Texcoords are in the range of 0-1 with their origin at top left
	if origL then
		l,r=low,high;
	elseif origR then
		l,r=1-high,1-low;
	end
	if origT then
		t,b=low,high;
	elseif origB then
		t,b=1-high,1-low;
	end

	--Process flip (affects which side the bar piece is drawn from too)
	if flipH then l,r=1-l,1-r; end
	if flipV then t,b=1-t,1-b; end

	--Constrain to crop size
	local cropL,cropR,cropT,cropB=math.min(cropx1,cropx2),math.max(cropx1,cropx2),math.min(cropy1,cropy2),math.max(cropy1,cropy2);
	local cropW,cropH=cropR-cropL,cropB-cropT;
	l,r,t,b=l*cropW+cropL,r*cropW+cropL,t*cropH+cropT,b*cropH+cropT;
	
	--Apply texcord/size
	bar:SetTexCoord(l,r,t,b);
	bar:SetWidth(pw*((origL or origR) and math.abs(high-low) or 1));
	bar:SetHeight(ph*((origT or origB) and math.abs(high-low) or 1));
end

--[[-----------------------------------------------------------------------------
Main Bar Creations
-------------------------------------------------------------------------------]]
local LeftHudBG = CreateFrame("Frame",nil, GHudMain);
local RightHudBG = CreateFrame("Frame",nil, GHudMain);
local PlayerHBar = CreateFrame("Frame",nil, GHudMain);
local PlayerMBar = CreateFrame("Frame",nil, GHudMain);
local TargetHBar = CreateFrame("Frame",nil, GHudMain);
local TargetMBar = CreateFrame("Frame",nil, GHudMain);
local PPetHBar = CreateFrame("Frame",nil, GHudMain);
local PPetMBar = CreateFrame("Frame",nil, GHudMain);

function addon:LayoutHudBars()
	PlayerHBar:ClearAllPoints()
	PlayerHBar:SetPoint("RIGHT", GHudMain, "LEFT", - addon.settings.hudWidth, addon.settings.hudHeight);-- Place frame wherever
	PlayerMBar:ClearAllPoints()
	PlayerMBar:SetPoint("LEFT", GHudMain, "RIGHT", addon.settings.hudWidth, addon.settings.hudHeight);
	
	TargetHBar:ClearAllPoints()
	TargetHBar:SetPoint("RIGHT", GHudMain, "LEFT", - addon.settings.hudWidth, addon.settings.hudHeight);-- Place frame wherever
	TargetMBar:ClearAllPoints()
	TargetMBar:SetPoint("LEFT", GHudMain, "RIGHT", addon.settings.hudWidth, addon.settings.hudHeight);

	PPetHBar:ClearAllPoints()
	PPetHBar:SetPoint("RIGHT", GHudMain, "LEFT", - addon.settings.hudWidth, addon.settings.hudHeight - 53);-- Place frame wherever
	PPetMBar:ClearAllPoints()
	PPetMBar:SetPoint("LEFT", GHudMain, "RIGHT", addon.settings.hudWidth, addon.settings.hudHeight - 53);
end

--[[-----------------------------------------------------------------------------
Main Bar Height and Width Settings.  This affects the texture stretching.
-------------------------------------------------------------------------------]]
--textured bars only will control bar height and width.
PlayerHBar:SetWidth(128);
PlayerHBar:SetHeight(233);
PlayerMBar:SetWidth(128);
PlayerMBar:SetHeight(233);

TargetHBar:SetWidth(128);
TargetHBar:SetHeight(250);
TargetMBar:SetWidth(128);
TargetMBar:SetHeight(250);

PPetHBar:SetWidth(128);
PPetHBar:SetHeight(109);
PPetMBar:SetWidth(128);
PPetMBar:SetHeight(109);

--main bars control background
LeftHudBG:SetWidth(128);
LeftHudBG:SetHeight(256);
RightHudBG:SetWidth(128);
RightHudBG:SetHeight(256);

--[[-----------------------------------------------------------------------------
Setup and change background function
-------------------------------------------------------------------------------]]
function addon:SetHudBackgrounds()
	if UnitExists("target") then
		if UnitExists("pet") then
			LeftHudBG.Background:SetTexture("Interface\\AddOns\\GrimUI\\HudSkins\\bg_21p");
			RightHudBG.Background:SetTexture("Interface\\AddOns\\GrimUI\\HudSkins\\bg_21p");
		else
			LeftHudBG.Background:SetTexture("Interface\\AddOns\\GrimUI\\HudSkins\\bg_21");
			RightHudBG.Background:SetTexture("Interface\\AddOns\\GrimUI\\HudSkins\\bg_21");
		end
	else
		if UnitExists("pet") then
			LeftHudBG.Background:SetTexture("Interface\\AddOns\\GrimUI\\HudSkins\\bg_1p");
			RightHudBG.Background:SetTexture("Interface\\AddOns\\GrimUI\\HudSkins\\bg_1p");
		else
			LeftHudBG.Background:SetTexture("Interface\\AddOns\\GrimUI\\HudSkins\\bg_1");
			RightHudBG.Background:SetTexture("Interface\\AddOns\\GrimUI\\HudSkins\\bg_1");
		end
	end
end

--Left Side Background texture
LeftHudBG.Background = LeftHudBG:CreateTexture(nil,"BACKGROUND");
LeftHudBG.Background:SetAllPoints(LeftHudBG);
LeftHudBG:SetPoint("CENTER", PlayerHBar, "CENTER")

--Right Side Background texture
RightHudBG:SetPoint("CENTER", PlayerMBar, "CENTER")
RightHudBG.Background = RightHudBG:CreateTexture(nil,"BACKGROUND");
RightHudBG.Background:SetAllPoints(RightHudBG);
RightHudBG.Background:SetTexCoord(1,0,0,1)

--[[-----------------------------------------------------------------------------
Set Hud Alpha
-------------------------------------------------------------------------------]]
function addon:SetHudAlpha()
		local hcur,hmax = UnitHealth("player"),UnitHealthMax("player")
		local pcur, pmax = UnitPower("player"), UnitPowerMax("player")
	if UnitAffectingCombat("player") then
		GHudMain:SetAlpha(0.90)
	else
		if hcur ~= hmax or pcur ~= pmax or UnitExists("target") then
			GHudMain:SetAlpha(0.50)
		else
			GHudMain:SetAlpha(0)
		end
	end
end

--[[-----------------------------------------------------------------------------
Player Bar Textures. 
-------------------------------------------------------------------------------]]
PlayerHBar.HealthBar = PlayerHBar:CreateTexture(nil,"ARTWORK");--Notice the change in layers, this makes the bar draw on top of the background
PlayerHBar.HealthBar:SetPoint("BOTTOM");--We need only one point set, in this example, the bar fills toward the right, so we need it left-aligned
PlayerHBar.HealthBar:SetWidth(128);
PlayerHBar.HealthBar:SetHeight(233);
PlayerHBar.HealthBar:SetTexture("Interface\\AddOns\\GrimUI\\HudSkins\\1");--Be sure to use the same image or one derived from the background

-- Player Mana Texture
PlayerMBar.ManaBar = PlayerMBar:CreateTexture(nil,"ARTWORK");--Notice the change in layers, this makes the bar draw on top of the background
PlayerMBar.ManaBar:SetPoint("BOTTOM");--We need only one point set, in this example, the bar fills toward the right, so we need it left-aligned
PlayerMBar.ManaBar:SetWidth(128);--Match frame width for now
PlayerMBar.ManaBar:SetHeight(233);--Match frame height for now
PlayerMBar.ManaBar:SetTexture("Interface\\AddOns\\GrimUI\\HudSkins\\1");--Be sure to use the same image or one derived from the background

--  Heal prediction texture (this'll be my example of a partial bar)
PlayerHBar.HealBar = PlayerHBar:CreateTexture(nil,"ARTWORK");--         Use the same layer as Healthbar
PlayerHBar.HealBar:SetPoint("BOTTOM");--                   Use the same point for the HealthBar
PlayerHBar.HealBar:SetWidth(128);--                    Match frame width for now
PlayerHBar.HealBar:SetHeight(256);--                    Match frame height for now
PlayerHBar.HealBar:SetTexture("Interface\\AddOns\\GrimUI\\HudSkins\\1");--  Be sure to use the same image or one derived from the background

PlayerHBar:RegisterEvent("PLAYER_ENTERING_WORLD");
PlayerHBar:RegisterEvent("UNIT_HEALTH", "player");
PlayerHBar:RegisterEvent("UNIT_HEALTH_PREDICTION");

PlayerHBar:SetScript("OnEvent",function(self,event)
	local hcur,hmax,heal=UnitHealth("player"),UnitHealthMax("player"),UnitGetIncomingHeals("player") or 0;--    UnitGetIncomingHeals() can return nil for unsupported units
	local hppcnt=hcur/math.max(1,hmax);
	local healpcnt=heal/math.max(1,hmax);
	--  Set our bars (notice the HealBar is a partial bar since it has a start value greater than zero)
	addon:SetBarValue(self.HealthBar,0,hppcnt, false, false, nil, nil, 12/256, 245/256);
	addon:SetBarValue(self.HealBar,hppcnt,hppcnt+healpcnt, false, false);
	--  This color formula ranges in color from green, to yellow, to red
	self.HealthBar:SetVertexColor(math.min(2-2*hppcnt,1),math.min(2*hppcnt,1),0);
end)

PlayerMBar:RegisterEvent("PLAYER_ENTERING_WORLD");
PlayerMBar:RegisterEvent("UNIT_POWER", "player");

PlayerMBar:SetScript("OnEvent",function(self,event)
	local pcur, pmax, ptype = UnitPower("player"), UnitPowerMax("player"), UnitPowerType("player");
	local mppcnt = pcur/math.max(1,pmax);
	--  Set our bars (notice the HealBar is a partial bar since it has a start value greater than zero)
	addon:SetBarValue(self.ManaBar,0,mppcnt, true, false, nil, nil, 12/256, 245/256);
	 if ptype == 0 then
		self.ManaBar:SetVertexColor(.556, .556, .921, 1)
	elseif ptype == 1 or 2 or 3 or 6 then
		self.ManaBar:SetVertexColor(.656, .456, .456, 1)
	end
end)

--[[-----------------------------------------------------------------------------
Target Bars Textures.  
-------------------------------------------------------------------------------]]
TargetHBar.HealthBar = TargetHBar:CreateTexture(nil,"ARTWORK");
TargetHBar.HealthBar:SetPoint("BOTTOM");
TargetHBar.HealthBar:SetWidth(128);
TargetHBar.HealthBar:SetHeight(256);
TargetHBar.HealthBar:SetTexture("Interface\\AddOns\\GrimUI\\HudSkins\\2");

TargetMBar.ManaBar = TargetMBar:CreateTexture(nil,"ARTWORK");
TargetMBar.ManaBar:SetPoint("BOTTOM");
TargetMBar.ManaBar:SetWidth(128);
TargetMBar.ManaBar:SetHeight(256);
TargetMBar.ManaBar:SetTexture("Interface\\AddOns\\GrimUI\\HudSkins\\2");

TargetHBar:RegisterEvent("PLAYER_ENTERING_WORLD");
TargetHBar:RegisterEvent("PLAYER_TARGET_CHANGED");
TargetHBar:RegisterEvent("UNIT_HEALTH", "target");
TargetHBar:RegisterEvent("UNIT_HEALTH_PREDICTION", "target");

TargetHBar:SetScript("OnEvent",function(self,event)
	local hcur,hmax,heal=UnitHealth("target"),UnitHealthMax("target"),UnitGetIncomingHeals("target") or 0;
	local hppcnt=hcur/math.max(1,hmax);
	local healpcnt=heal/math.max(1,hmax);
	addon:SetBarValue(self.HealthBar,0,hppcnt, false, false, nil, nil, 4/256, 253/256);
	--addon:SetBarValue(self.HealBar,hppcnt,hppcnt+healpcnt);
	self.HealthBar:SetVertexColor(math.min(2-2*hppcnt,1),math.min(2*hppcnt,1),0);
end)

TargetMBar:RegisterEvent("PLAYER_ENTERING_WORLD");
TargetMBar:RegisterEvent("PLAYER_TARGET_CHANGED");
TargetMBar:RegisterEvent("UNIT_POWER", "target");

TargetMBar:SetScript("OnEvent",function(self,event)
	local pcur, pmax, ptype = UnitPower("target"), UnitPowerMax("target"), UnitPowerType("target");
	local mppcnt = pcur/math.max(1,pmax);
	addon:SetBarValue(self.ManaBar,0,mppcnt, true, false, nil, nil, 4/256, 253/256);
	 if ptype == 0 then
		self.ManaBar:SetVertexColor(.556, .556, .921, 1)
	elseif ptype == 1 or 2 or 3 or 6 then
		self.ManaBar:SetVertexColor(.656, .456, .456, 1)
	end
end)

--[[-----------------------------------------------------------------------------
Pet Bars Textures.  Match Height and Width to texture file size.
-------------------------------------------------------------------------------]]
PPetHBar.HealthBar = PPetHBar:CreateTexture(nil,"ARTWORK");
PPetHBar.HealthBar:SetPoint("BOTTOM");
PPetHBar.HealthBar:SetWidth(128);
PPetHBar.HealthBar:SetHeight(156);
PPetHBar.HealthBar:SetTexture("Interface\\AddOns\\GrimUI\\HudSkins\\p1");

PPetMBar.ManaBar = PPetMBar:CreateTexture(nil,"ARTWORK");
PPetMBar.ManaBar:SetPoint("BOTTOM");
PPetMBar.ManaBar:SetWidth(128);
PPetMBar.ManaBar:SetHeight(156);
PPetMBar.ManaBar:SetTexture("Interface\\AddOns\\GrimUI\\HudSkins\\p1");

PPetHBar:RegisterEvent("PLAYER_ENTERING_WORLD");
PPetHBar:RegisterEvent("PLAYER_TARGET_CHANGED");
PPetHBar:RegisterEvent("UNIT_HEALTH", "pet")
PPetHBar:RegisterEvent("UNIT_LEVEL", "pet")
PPetHBar:RegisterEvent("UNIT_AURA", "pet")
PPetHBar:RegisterEvent("UNIT_MAXHEALTH", "pet")
PPetHBar:RegisterEvent("PLAYER_PET_CHANGED")
PPetHBar:RegisterEvent("UNIT_PET", "player")
PPetHBar:RegisterEvent("UNIT_HEALTH_PREDICTION", "pet");

PPetHBar:SetScript("OnEvent",function(self,event)
	local hcur,hmax,heal=UnitHealth("pet"),UnitHealthMax("pet"),UnitGetIncomingHeals("pet") or 0;
	local hppcnt=hcur/math.max(1,hmax);
	local healpcnt=heal/math.max(1,hmax);
	addon:SetBarValue(self.HealthBar,0,hppcnt, false, false, nil, nil, 127/256, 236/256);
	--addon:SetBarValue(self.HealBar,hppcnt,hppcnt+healpcnt);
	self.HealthBar:SetVertexColor(math.min(2-2*hppcnt,1),math.min(2*hppcnt,1),0);
end)

PPetMBar:RegisterEvent("PLAYER_ENTERING_WORLD");
PPetMBar:RegisterEvent("UNIT_HEALTH", "pet")
PPetMBar:RegisterEvent("UNIT_LEVEL", "pet")
PPetMBar:RegisterEvent("UNIT_MANA", "pet")
PPetMBar:RegisterEvent("UNIT_AURA", "pet")
PPetMBar:RegisterEvent("UNIT_DISPLAYPOWER", "pet")
PPetMBar:RegisterEvent("UNIT_ENERGY", "pet")
PPetMBar:RegisterEvent("UNIT_MAXENERGY", "pet")
PPetMBar:RegisterEvent("UNIT_MAXMANA", "pet")

PPetMBar:RegisterEvent("PET_UI_UPDATE");
PPetMBar:RegisterEvent("PLAYER_TARGET_CHANGED");
PPetMBar:RegisterEvent("UNIT_POWER", "pet");

PPetMBar:SetScript("OnEvent",function(self,event)
	local pcur, pmax, ptype = UnitPower("pet"), UnitPowerMax("pet"), UnitPowerType("pet");
	local mppcnt = pcur/math.max(1,pmax);
	addon:SetBarValue(self.ManaBar,0,mppcnt, true, false, nil, nil, 127/256, 236/256);
	if ptype == 0 then
		self.ManaBar:SetVertexColor(.556, .556, .921, 1)
	elseif ptype == 1 or 2 or 3 or 6 then
		self.ManaBar:SetVertexColor(.656, .456, .456, 1)
	end
end)

--[[-----------------------------------------------------------------------------
Addon Loaded Initialize
-------------------------------------------------------------------------------]]
addon.RegisterEvent("HUD-Initialize", 'ADDON_LOADED', function(self, event)
	addon.UnregisterEvent(self, event)
	addon:SetupGHud()
	addon:LayoutHudBars()
	addon:SetHudAlpha()
	addon:SetHudBackgrounds()
	addon:GHudScale()
end)