
NURFED_SAVED_HUD = {};
local player = nil;
local saved = {};
local version = "01.18.2006";

local lib = Nurfed_Hud:New();
local utility = Nurfed_Utility:New();

local checks = {};
local sliders = {};
local inputs = {};

function Nurfed_Hud_OnLoad()
	this:RegisterEvent("PLAYER_LOGIN");
	this:RegisterEvent("PLAYER_ENTERING_WORLD");
	this:RegisterEvent("PLAYER_COMBO_POINTS");
	this:RegisterEvent("PLAYER_REGEN_ENABLED");
	this:RegisterEvent("PLAYER_REGEN_DISABLED");
	this:RegisterEvent("PLAYER_TARGET_CHANGED");
	this:RegisterEvent("UNIT_PET");
	this:RegisterEvent("UNIT_AURA");
	this:RegisterEvent("UNIT_HEALTH");
	this:RegisterEvent("UNIT_MAXHEALTH");
	this:RegisterEvent("UNIT_MANA");
	this:RegisterEvent("UNIT_RAGE");
	this:RegisterEvent("UNIT_FOCUS");
	this:RegisterEvent("UNIT_ENERGY");
	this:RegisterEvent("UNIT_MAXMANA");
	this:RegisterEvent("UNIT_MAXRAGE");
	this:RegisterEvent("UNIT_MAXFOCUS");
	this:RegisterEvent("UNIT_MAXENERGY");
	this:RegisterEvent("UNIT_DISPLAYPOWER");
end

function Nurfed_Hud_OnEvent(event)
	if (event == "PLAYER_LOGIN") then
		this:UnregisterEvent(event);
		player = UnitName("player").." - "..GetRealmName();

		if (not NURFED_SAVED_HUD[player]) then
			NURFED_SAVED_HUD[player] = utility:TableCopy(lib.Default);
		else
			Nurfed_UpdateHudSaved();
		end
		Nurfed_Hud_Init();
		return;
	end

	if (event == "PLAYER_ENTERING_WORLD") then
		lib:UpdateHud();
		return;
	end

	if (event == "PLAYER_REGEN_ENABLED") then
		lib.inCombat = nil;
		lib:UpdateHud();
		return;
	end

	if (event == "PLAYER_REGEN_DISABLED") then
		lib.inCombat = true;
		lib:UpdateHud();
		return;
	end

	if (event == "PLAYER_COMBO_POINTS") then
		lib:UpdateCombo();
		return;
	end

	if (event == "PLAYER_TARGET_CHANGED") then
		lib:UpdateTarget();
		return;
	end

	if (arg1 == "player" or arg1 == "pet" or arg1 == "target") then
		if (event == "UNIT_PET") then
			lib:UpdatePet();
			return;
		end

		if (event == "UNIT_AURA") then
			if (arg1 == "player" or arg1 == "target") then
				lib:UpdateAuras(arg1);
			end
			return;
		end

		if (event == "UNIT_HEALTH" or event == "UNIT_MAXHEALTH") then
			lib:UpdateHealth(arg1);
			return;
		end

		if (event == "UNIT_MANA" or event == "UNIT_RAGE" or event == "UNIT_FOCUS" or event == "UNIT_ENERGY" or event == "UNIT_MAXMANA" or event == "UNIT_MAXRAGE" or event == "UNIT_MAXFOCUS" or event == "UNIT_MAXENERGY") then
			lib:UpdateMana(arg1);
			return;
		end

		if (event == "UNIT_DISPLAYPOWER") then
			lib:UpdateManaColor(arg1);
			return;
		end
	end
end

function Nurfed_UpdateHudSaved()
	for k, v in lib.Default do
		if (not NURFED_SAVED_HUD[player][k]) then
			NURFED_SAVED_HUD[player][k] = v;
		elseif (type(v) ~= type(NURFED_SAVED_HUD[player][k])) then
			NURFED_SAVED_HUD[player][k] = nil;
			NURFED_SAVED_HUD[player][k] = v;
		end
	end
end

function Nurfed_Hud_Init()
	saved = NURFED_SAVED_HUD[player];
	utility:AddLockFunc(Nurfed_Hud_Lock);
	lib:Init();
	Nurfed_Hud_Lock();
end

function Nurfed_Hud_OnMouseUp()
	if (IsControlKeyDown()) then
	else
		this:StopMovingOrSizing();
		local world = getglobal("UIParent");
		local screenW = (world:GetRight() - world:GetLeft()) / 2;
		local screenH = (world:GetTop() - world:GetBottom()) / 2;
		saved[this:GetName()].x = this:GetLeft() + (this:GetRight() - this:GetLeft()) / 2 - screenW;
		saved[this:GetName()].y = this:GetBottom() + (this:GetTop() - this:GetBottom()) / 2 - screenH;
	end
end

function Nurfed_Hud_OnMouseDown()
	if (IsControlKeyDown()) then
	else
		this:StartMoving();
	end
end

function Nurfed_Hud_CastingOnEvent()
	if ( event == "SPELLCAST_START" ) then
		Nurfed_Hud_CastingTexture:SetVertexColor(1.0, 1.0, 0.0);
		this.startTime = GetTime();
		this.maxValue = this.startTime + (arg2 / 1000);
		this:SetAlpha(1.0);
		this.holdTime = 0;
		this.casting = 1;
		this.fadeOut = nil;
		Nurfed_Hud_CastingNameTextText:SetText(arg1);
		Nurfed_Hud_CastingNameText:Show();
		Nurfed_Hud_CastingTimeText:Show();
		this:Show();

		this.mode = "casting";
	elseif ( event == "SPELLCAST_STOP" ) then
		if ( not this:IsVisible() ) then
			this:Hide();
		end
		if ( this:IsShown() ) then
			Nurfed_Hud_CastingTexture:SetVertexColor(0.0, 1.0, 0.0);
			this.casting = nil;
			this.flash = 1;
			this.fadeOut = 1;

			this.mode = "flash";
		end
	elseif ( event == "SPELLCAST_FAILED" or event == "SPELLCAST_INTERRUPTED" ) then
		if ( this:IsShown() ) then
			CastingBarFrameStatusBar:SetValue(this.maxValue);
			Nurfed_Hud_CastingTexture:SetVertexColor(1.0, 0.0, 0.0);
			if ( event == "SPELLCAST_FAILED" ) then
				Nurfed_Hud_CastingNameTextText:SetText(FAILED);
			else
				Nurfed_Hud_CastingNameTextText:SetText(INTERRUPTED);
			end
			this.casting = nil;
			this.fadeOut = 1;
			this.holdTime = GetTime() + CASTING_BAR_HOLD_TIME;
		end
	elseif ( event == "SPELLCAST_DELAYED" ) then
		if( this:IsShown() ) then
			this.startTime = this.startTime + (arg1 / 1000);
			this.maxValue = this.maxValue + (arg1 / 1000);
		end
	elseif ( event == "SPELLCAST_CHANNEL_START" ) then
		Nurfed_Hud_CastingTexture:SetVertexColor(1.0, 0.7, 0.0);
		this.maxValue = 1;
		this.startTime = GetTime();
		this.endTime = this.startTime + (arg1 / 1000);
		this.duration = arg1 / 1000;
		this:SetAlpha(1.0);
		this.holdTime = 0;
		this.casting = nil;
		this.channeling = 1;
		this.fadeOut = nil;
		Nurfed_Hud_CastingNameTextText:SetText(arg2);
		Nurfed_Hud_CastingNameText:Show();
		Nurfed_Hud_CastingTimeText:Show();
		this:Show();
	elseif ( event == "SPELLCAST_CHANNEL_UPDATE" ) then
		if ( arg1 == 0 ) then
			this.channeling = nil;
		elseif ( this:IsShown() ) then
			local origDuration = this.endTime - this.startTime
			this.endTime = GetTime() + (arg1 / 1000)
			this.startTime = this.endTime - origDuration
		end
	end
end

function Nurfed_Hud_CastingOnUpdate()
	if (lib.Shown) then
		return;
	end
	if ( this.casting ) then
		local status = GetTime();
		if ( status > this.maxValue ) then
			status = this.maxValue
		end
		lib:UpdateCasting((status - this.startTime), (this.maxValue - this.startTime));
		Nurfed_Hud_CastingTimeTextText:SetText(string.format(" (%.1fs)", this.maxValue - status));
	elseif ( this.channeling ) then
		local time = GetTime();
		if ( time > this.endTime ) then
			time = this.endTime
		end
		if ( time == this.endTime ) then
			this.channeling = nil;
			this.fadeOut = 1;
			return;
		end
		local barValue = this.startTime + (this.endTime - time);
		lib:UpdateCasting((barValue - this.startTime), (this.endTime - this.startTime));
		Nurfed_Hud_CastingTimeTextText:SetText(string.format(" (%.1fs)", this.endTime - time));
	elseif ( GetTime() < this.holdTime ) then
		return;
	elseif (this.fadeOut) then
		local alpha = this:GetAlpha() - CASTING_BAR_ALPHA_STEP;
		if ( alpha > 0 ) then
			this:SetAlpha(alpha);
		else
			Nurfed_Hud_CastingNameText:Hide();
			Nurfed_Hud_CastingTimeText:Hide();
			this.fadeOut = nil;
			this:Hide();
		end
	end
end

function Nurfed_Hud_Lock()
	local frame;
	for k, v in saved do
		frame = getglobal(k);
		if (frame) then
			if (NURFED_LOCKALL == 1) then
				lib.Shown = nil;
				frame:EnableMouse(0);
			else
				lib.Shown = true;
				frame:EnableMouse(1);
				frame:SetAlpha(1);
				frame:Show();

				if (string.find(frame:GetName(), "Debuff")) then
					local texture = getglobal(frame:GetName().."Texture");
					texture:SetTexture("Interface\\Icons\\Spell_Shadow_FingerOfDeath");
				end

				if (string.find(frame:GetName(), "Text")) then
					local text = getglobal(frame:GetName().."Text");
					local name = getglobal(string.upper(string.gsub(frame:GetName(), "_", "")));
					text:SetText(name);
				end
			end
		end
	end
	lib:UpdateHud();
	Nurfed_Hud_Casting.fadeOut = 1;
end

function Nurfed_HudOptions_Reset()
	NURFED_SAVED_HUD[player] = nil;
	NURFED_SAVED_HUD[player] = utility:TableCopy(lib.Default);
	Nurfed_Hud_Init();
end

function Nurfed_HudOptions_OnShow()
	this:SetHeight(360);
	this:SetWidth(500);
	Nurfed_HudOptionsFrame:SetHeight(330);
	Nurfed_HudOptionsFrame:SetWidth(492);
	Nurfed_HudOptionsFrameHeadline:SetWidth(480);
	Nurfed_HudOptionsFrameHeadline:SetText("Nurfed Hud - "..version);

	Nurfed_HudOptionsFrameVars:SetBackdropColor(0, 0, 0, 0.75);
	Nurfed_HudOptionsFrameVars:SetBackdropBorderColor(1, 1, 1, 1);
	Nurfed_HudOptionsFrameVars:Show();
end

function Nurfed_HudOptionsInit()
	checks = {
		[1] = { name = "Show In Combat", option = "incombat", func = function() lib:UpdateHud() end },
		[2] = { name = "Combo Point Textures", option = "comboimg", func = function() lib:UpdateCombo() end },
		[3] = { name = "Combo Point Text", option = "combotxt", func = function() lib:UpdateCombo() end },
		[4] = { name = "Player Debuffs", option = "playerdebuffs", func = function() lib:UpdateAuras("player") end },
		[5] = { name = "Target Debuffs", option = "targetdebuffs", func = function() lib:UpdateAuras("target") end },
		[6] = { name = "Player HP Text", option = "playerhptext", func = function() lib:UpdateHealth("player") end },
		[7] = { name = "Player MP Text", option = "playermptext", func = function() lib:UpdateMana("player") end },
		[8] = { name = "Target HP Text", option = "targethptext", func = function() lib:UpdateHealth("target") end },
		[9] = { name = "Target MP Text", option = "targetmptext", func = function() lib:UpdateMana("target") end },
		[10] = { name = "Pet HP Text", option = "pethptext", func = function() lib:UpdateHealth("pet") end },
		[11] = { name = "Pet MP Text", option = "petmptext", func = function() lib:UpdateMana("pet") end },
		[12] = { name = "Casting Bar", option = "casting", func = function() lib:InitCastBar("casting") end },
		[13] = { name = "Blizz Casting Bar", option = "blizzcasting", func = function() lib:InitCastBar("blizzcasting") end },
	};

	sliders = {
		[1] = { name = "Non-Combat Alpha", option = "alpha", min = 0, max = 1, step = 0.01, func = function() lib:UpdateHud() end },
		[2] = { name = "Background Alpha", option = "bgalpha", min = 0, max = 1, step = 0.01, func = function() lib:UpdateBG() end },
		[3] = { name = "Debuff Alpha", option = "debuffalpha", min = 0, max = 1, step = 0.01 },
		[4] = { name = "Player Debuff Limit", option = "playerdebuffcount", min = 0, max = 16, step = 1 },
		[5] = { name = "Target Debuff Limit", option = "targetdebuffcount", min = 0, max = 16, step = 1 },
	};

	inputs = {
		[1] = {name = "Player HP Format", option = "playerhpformat", func = function() lib:UpdateHealth("player") end },
		[2] = {name = "Player MP Format", option = "playermpformat", func = function() lib:UpdateMana("player") end },
		[3] = {name = "Target HP Format", option = "targethpformat", func = function() lib:UpdateHealth("target") end },
		[4] = {name = "Target MP Format", option = "targetmpformat", func = function() lib:UpdateMana("target") end },
		[5] = {name = "Pet HP Format", option = "pethpformat", func = function() lib:UpdateHealth("pet") end },
		[6] = {name = "Pet MP Format", option = "petmpformat", func = function() lib:UpdateMana("pet") end },
	};
end

function Nurfed_HudOptionsFrameCheckOnShow()
	local id = this:GetID();
	local text = getglobal(this:GetName().."Text");
	local value = saved[checks[id].option];
	local align = checks[id].align;
	if (align == "right") then
		text:ClearAllPoints();
		text:SetPoint("RIGHT", this:GetName(), "LEFT", 0, 0);
	end
	text:SetText(checks[id].name);
	if (value == 1) then
		text:SetTextColor(0,1,0);
	else
		text:SetTextColor(1,0,0);
	end
	this:SetChecked(value);
end

function Nurfed_HudOptionsFrameCheckOnClick()
	local id = this:GetID();
	local text = getglobal(this:GetName().."Text");
	local func = checks[id].func;
	local value;
	if (this:GetChecked() == 1) then
		text:SetTextColor(0,1,0);
		value = 1;
	else
		text:SetTextColor(1,0,0);
		value = 0;
	end
	saved[checks[id].option] = value;
	if (func) then
		func();
	end
end

function Nurfed_HudOptionsFrameSliderOnShow()
	local id = this:GetID();
	local text = getglobal(this:GetName().."Text");
	local minLabel = getglobal(this:GetName().."Low");
	local maxLabel = getglobal(this:GetName().."High");
	text:SetText(sliders[id].name);
	minLabel:SetText(sliders[id].min);
	maxLabel:SetText(sliders[id].max);
	this:SetMinMaxValues(sliders[id].min, sliders[id].max);
	this:SetValueStep(sliders[id].step);
	this:SetValue(saved[sliders[id].option]);
end

function Nurfed_HudOptionsFrameSliderOnValueChanged()
	local id = this:GetID();
	local text = getglobal(this:GetName().."Value");
	local value = this:GetValue();
	if (strfind(value, ".")) then
		value = format("%.2f", value);
	end
	local func = sliders[id].func;
	text:SetText("("..value..")");
	text:ClearAllPoints();
	if (this:GetValue() < ((sliders[id].max - sliders[id].min) / 4) + sliders[id].min) then
		text:SetPoint("LEFT", this:GetName().."Thumb", "RIGHT", -6, 0);
	else
		text:SetPoint("RIGHT", this:GetName().."Thumb", "LEFT", 6, 0);
	end
	if (this.tip ~=1) then return; end
	local option = sliders[id].option;
	saved[option] = this:GetValue();
	if (func) then
		func();
	end
end

function Nurfed_HudOptionsFrameInputOnShow()
	local id = this:GetID();
	local text = getglobal(this:GetName().."Text");
	local inputtext = getglobal(this:GetName().."Input");
	local option = inputs[id].option;
	text:SetText(inputs[id].name);
	inputtext:SetText(saved[option]);
end

function Nurfed_HudOptionsFrameSetInput()
	local id = this:GetParent():GetID();
	local inputtext = getglobal(this:GetParent():GetName().."Input");
	local text = inputtext:GetText();
	local option = inputs[id].option;
	local func = inputs[id].func;
	inputtext:ClearFocus();
	saved[option] = text;
	if (func) then
		func();
	end
end

function Nurfed_Hud_Config()
	if (Nurfed_HudOptions:IsVisible()) then
		HideUIPanel(Nurfed_HudOptions);
	else
		ShowUIPanel(Nurfed_HudOptions);
	end
end
