--[[
	Cooldown Alert

	By sarf

	This mod ...

	Thanks goes to 
	
	CosmosUI URL:
	http://www.cosmosui.org/forums/viewtopic.php?t=
	
   ]]


-- Constants

-- Variables
CooldownAlert_Enabled = 0;
CooldownAlert_ImminenceTime = 1.0;

CooldownAlert_Saved_UseAction = nil;
CooldownAlert_Saved_SpellButton_OnClick = nil;
CooldownAlert_Cosmos_Registered = 0;

-- executed on load, calls general set-up functions
function CooldownAlert_OnLoad()
	CooldownAlert_Register();
end

-- registers the mod with Cosmos
function CooldownAlert_Register_Cosmos()
	if ( ( Cosmos_RegisterConfiguration ) and ( CooldownAlert_Cosmos_Registered == 0 ) ) then
		Cosmos_RegisterConfiguration(
			"COS_COOLDOWNALERT",
			"SECTION",
			TEXT(COOLDOWNALERT_CONFIG_HEADER),
			TEXT(COOLDOWNALERT_CONFIG_HEADER_INFO)
		);
		Cosmos_RegisterConfiguration(
			"COS_COOLDOWNALERT_HEADER",
			"SEPARATOR",
			TEXT(COOLDOWNALERT_CONFIG_HEADER),
			TEXT(COOLDOWNALERT_CONFIG_HEADER_INFO)
		);
		Cosmos_RegisterConfiguration(
			"COS_COOLDOWNALERT_ENABLED",
			"CHECKBOX",
			TEXT(COOLDOWNALERT_ENABLED),
			TEXT(COOLDOWNALERT_ENABLED_INFO),
			CooldownAlert_Toggle_Enabled,
			CooldownAlert_Enabled
		);
		if ( Cosmos_RegisterChatCommand ) then
			local CooldownAlertEnableCommands = {"/cooldownalerttoggle","/cdatoggle","/cooldownalertenable","/cdaenable","/cooldownalertdisable","/cdadisable"};
			Cosmos_RegisterChatCommand (
				"COOLDOWNALERT_ENABLE_COMMANDS", -- Some Unique Group ID
				CooldownAlertEnableCommands, -- The Commands
				CooldownAlert_Enable_ChatCommandHandler,
				COOLDOWNALERT_CHAT_COMMAND_ENABLE_INFO -- Description String
			);
		end
		CooldownAlert_Cosmos_Registered = 1;
	end
end

-- registers the mod with the system, integrating it with slash commands and "master" AddOns
function CooldownAlert_Register()
	if ( Cosmos_RegisterConfiguration ) then
		CooldownAlert_Register_Cosmos();
	else
		SlashCmdList["COOLDOWNALERTSLASHENABLE"] = CooldownAlert_Enable_ChatCommandHandler;
		SLASH_COOLDOWNALERTSLASHENABLE1 = "/cooldownalertenable";
		SLASH_COOLDOWNALERTSLASHENABLE2 = "/cdaenable";
		SLASH_COOLDOWNALERTSLASHENABLE3 = "/cooldownalertdisable";
		SLASH_COOLDOWNALERTSLASHENABLE4 = "/cdadisable";
		SLASH_COOLDOWNALERTSLASHENABLE5 = "/cooldownalerttoggle";
		SLASH_COOLDOWNALERTSLASHENABLE6 = "/cdatoggle";
		this:RegisterEvent("VARIABLES_LOADED");
	end

end

-- Handles chat - e.g. slashcommands - enabling/disabling the CooldownAlert
function CooldownAlert_Enable_ChatCommandHandler(msg)
	msg = string.lower(msg);
	
	-- Toggle appropriately
	if ( (string.find(msg, 'on')) or ((string.find(msg, '1')) and (not string.find(msg, '-1')) ) ) then
		CooldownAlert_Toggle_Enabled(1);
	else
		if ( (string.find(msg, 'off')) or (string.find(msg, '0')) ) then
			CooldownAlert_Toggle_Enabled(0);
		else
			CooldownAlert_Toggle_Enabled(-1);
		end
	end
end

-- Does things with the hooked function
function CooldownAlert_SpellButton_OnClick(drag)
	if ( CooldownAlert_Enabled == 1 ) then
		local id = SpellBook_GetSpellID(this:GetID());
		
		if ( IsControlKeyDown() ) then
			CooldownAlert_ToggleSpellAlert(id, SpellBookFrame.bookType);
			return;
		end
	end
	CooldownAlert_Saved_SpellButton_OnClick(drag);
end

function CooldownAlert_UseAction(id, something, onSelf)
	if ( CooldownAlert_Enabled == 1 ) then
		if ( IsControlKeyDown() ) then
			CooldownAlert_ToggleActionAlert(id);
			return;
		end
	end
	CooldownAlert_Saved_UseAction(id, something, onSelf);
end

COOLDOWNALERT_TYPE_SPELL = 1;
COOLDOWNALERT_TYPE_ACTION = 2;

CooldownAlert_WatchedStuff = {};

function CooldownAlert_GetActionName(pId)
	local name = nil;
	if ( CooldownAlertTooltip:SetAction(pId) ) then
		local nameText = getglobal("CooldownAlertTooltipTextLeft1");
		if ( nameText ) then
			name = nameText:GetText();
		else
			name = nil;
		end
	end
	return name;
end

function CooldownAlert_GetSpellName(pId, pSpellBook)
	return GetSpellName(pId, pSpellBook);
end


function CooldownAlert_AddSpell(pId, pSpellBook)
	if ( CooldownAlert_FindSpellIndex(pId, spellBook) == -1) then
		local newRegistrar = {};
		newRegistrar.id = pId;
		newRegistrar.spellBook = pSpellBook;
		newRegistrar.stuffType = COOLDOWNALERT_TYPE_SPELL;
		table.insert(CooldownAlert_WatchedStuff, newRegistrar);
	end
end

function CooldownAlert_AddAction(pId)
	if ( CooldownAlert_FindActionIndex(id) == -1) then
		local newRegistrar = {};
		newRegistrar.id = pId;
		newRegistrar.stuffType = COOLDOWNALERT_TYPE_ACTION;
		table.insert(CooldownAlert_WatchedStuff, newRegistrar);
	end
end

function CooldownAlert_FindSpellIndex(pId, pSpellBook)
	for k, v in CooldownAlert_WatchedStuff do
		if ( ( v.stuffType == COOLDOWNALERT_TYPE_SPELL ) and ( v.id == pId ) and ( v.spellBook == pSpellBook ) ) then
			return k;
		end
	end
	return -1;
end

function CooldownAlert_FindActionIndex(pId)
	for k, v in CooldownAlert_WatchedStuff do
		if ( ( v.stuffType == COOLDOWNALERT_TYPE_ACTION ) and ( v.id == pId) ) then
			return k;
		end
	end
	return -1;
end

function CooldownAlert_ToggleSpellAlert(pId, pSpellBook)
	local name, subname = CooldownAlert_GetSpellName(pId, pSpellBook);
	if ( ( subname ) and ( strlen(subname) > 0 ) ) then
		name = name.."("..subname..")";
	end
	local index = CooldownAlert_FindSpellIndex(pId, pSpellBook);
	if ( index > -1 ) then
		table.remove(CooldownAlert_WatchedStuff, index);
		CooldownAlert_Print(format(COOLDOWNALERT_CHAT_STUFF_REMOVED, name));
	else
		CooldownAlert_AddSpell(pId, pSpellBook);
		CooldownAlert_Print(format(COOLDOWNALERT_CHAT_STUFF_ADDED, name));
	end
end

function CooldownAlert_ToggleActionAlert(pId)
	local index = CooldownAlert_FindActionIndex(pId);
	if ( index > -1 ) then
		table.remove(CooldownAlert_WatchedStuff, index);
		CooldownAlert_Print(format(COOLDOWNALERT_CHAT_STUFF_REMOVED, CooldownAlert_GetActionName(pId)));
	else
		CooldownAlert_AddAction(pId);
		CooldownAlert_Print(format(COOLDOWNALERT_CHAT_STUFF_ADDED, CooldownAlert_GetActionName(pId)));
	end
end

function CooldownAlert_CheckForImminentCooldown()
	local start, duration, enable, name;
	local currentTime = GetTime();
	local imminenceList = {};
	for k, v in CooldownAlert_WatchedStuff do
		if ( v.stuffType == COOLDOWNALERT_TYPE_ACTION ) then
			start, duration, enable = GetActionCooldown(v.id);
		elseif ( v.stuffType == COOLDOWNALERT_TYPE_SPELL ) then
			start, duration, enable = GetSpellCooldown(v.id, v.spellBook);
		end
		if ( ( start > 0 ) and ( duration > 0 ) and ( ( start+duration + CooldownAlert_ImminenceTime ) < currentTime ) ) then
			if ( v.stuffType == COOLDOWNALERT_TYPE_ACTION ) then
				name = CooldownAlert_GetActionName(v.id);
			elseif ( v.stuffType == COOLDOWNALERT_TYPE_SPELL ) then
				name = CooldownAlert_GetSpellName(v.id, v.spellBook);
			end
			if ( name ) then
				table.insert(imminenceList, name);
			end
		end
	end
	local size = getn(imminenceList);
	if ( size > 0 ) then
		
		local msg = "";
		
		for i = 1, size do
			msg = msg..imminenceList[i];
			if ( i < (size-1) ) then 
				msg = msg..", ";
			elseif ( i == (size-1) ) then 
				msg = msg..", ";
			end
		end
		msg = msg.." has finished ";
		if ( size > 1 ) then
			msg = msg.."their";
		else
			msg = msg.."its";
		end
		msg = msg.." cooldown.";
	    ZoneTextString:SetText(msg);
	    ZoneTextString:SetTextColor(0.2, 1.0, 0.2);
	    ZoneTextFrame.startTime = GetTime();
	    ZoneTextFrame:Show();
		PlaySoundFile("Sound\\Doodad\\BellTollAlliance.wav");
	end
end

function CooldownAlert_OnUpdate(elapsed)
	
end


-- Hooks/unhooks functions. If toggle is 1, hooks functions, otherwise it unhooks functions.
--  Hooking functions mean that you replace them with your own functions and then call the 
--  original function at your leisure.
function CooldownAlert_Setup_Hooks(toggle)
	if ( toggle == 1 ) then
		if ( ( SpellButton_OnClick ~= CooldownAlert_SpellButton_OnClick ) and (CooldownAlert_Saved_SpellButton_OnClick == nil) ) then
			CooldownAlert_Saved_SpellButton_OnClick = SpellButton_OnClick;
			SpellButton_OnClick = CooldownAlert_SpellButton_OnClick;
		end
		if ( ( UseAction ~= CooldownAlert_UseAction ) and (CooldownAlert_Saved_UseAction == nil) ) then
			CooldownAlert_Saved_UseAction = UseAction;
			UseAction = CooldownAlert_UseAction;
		end
	else
		if ( SpellButton_OnClick == CooldownAlert_SpellButton_OnClick) then
			SpellButton_OnClick = CooldownAlert_Saved_SpellButton_OnClick;
			CooldownAlert_Saved_SpellButton_OnClick = nil;
		end

		if ( UseAction == CooldownAlert_UseAction) then
			UseAction = CooldownAlert_Saved_UseAction;
			CooldownAlert_Saved_UseAction = nil;
		end
	end
end

-- Handles events
function CooldownAlert_OnEvent(event)
	if ( event == "VARIABLES_LOADED" ) then
		if ( CooldownAlert_Cosmos_Registered == 0 ) then
			local value = getglobal("COS_COOLDOWNALERT_ENABLED_X");
			if (value == nil ) then
				-- defaults to off
				value = 0;
			end
			CooldownAlert_Toggle_Enabled(value);
		end
	end
end

-- Toggles the enabled/disabled state of an option and returns the new state
--  if toggle is 1, it's enabled
--  if toggle is 0, it's disabled
--   otherwise, it's toggled
function CooldownAlert_Generic_Toggle(toggle, variableName, CVarName, enableMessage, disableMessage)
	local oldvalue = getglobal(variableName);
	local newvalue = toggle;
	if ( ( toggle ~= 1 ) and ( toggle ~= 0 ) ) then
		if (oldvalue == 1) then
			newvalue = 0;
		elseif ( oldvalue == 0 ) then
			newvalue = 1;
		else
			newvalue = 0;
		end
	end
	setglobal(variableName, newvalue);
	setglobal(CVarName, newvalue);
	if ( newvalue ~= oldvalue ) then
		if ( newvalue == 1 ) then
			CooldownAlert_Print(TEXT(getglobal(enableMessage)));
		else
			CooldownAlert_Print(TEXT(getglobal(disableMessage)));
		end
	end
	CooldownAlert_Register_Cosmos();
	if ( CooldownAlert_Cosmos_Registered == 0 ) then 
		RegisterForSave(CVarName);
	end
	return newvalue;
end

-- Toggles the enabled/disabled state of the CooldownAlert
--  if toggle is 1, it's enabled
--  if toggle is 0, it's disabled
--   otherwise, it's toggled
function CooldownAlert_Toggle_Enabled(toggle)
	local newvalue = CooldownAlert_Generic_Toggle(toggle, "CooldownAlert_Enabled", "COS_COOLDOWNALERT_ENABLED_X", "COOLDOWNALERT_CHAT_ENABLED", "COOLDOWNALERT_CHAT_DISABLED");
	CooldownAlert_Setup_Hooks(newvalue);
end

-- Prints out text to a chat box.
function CooldownAlert_Print(msg,r,g,b,frame,id,unknown4th)
	if(unknown4th) then
		local temp = id;
		id = unknown4th;
		unknown4th = id;
	end
				
	if (not r) then r = 1.0; end
	if (not g) then g = 1.0; end
	if (not b) then b = 1.0; end
	if ( frame ) then 
		frame:AddMessage(msg,r,g,b,id,unknown4th);
	else
		if ( DEFAULT_CHAT_FRAME ) then 
			DEFAULT_CHAT_FRAME:AddMessage(msg, r, g, b,id,unknown4th);
		end
	end
end
