--[[ 
	ABInfo
]]--


----------------------------------------------------------------------------------------
-- VARS
----------------------------------------------------------------------------------------

ABI_SHINE_HEIGHT = 256;
ABI_SHINE_WIDTH  = 256;

ABI_NORMALBAR 		= 1;
ABI_BONUSBAR 		= 2;
ABI_MULTIBAR_FIRST 	= 3;
ABI_MULTIBAR_LAST 	= 6;
ABI_PETBAR 		= 7;
ABI_SHAPEBAR 		= 8;

ABI_PlayerClass = "";

ABI_SavedInfo = {
	["UseCooldown"] 	= true,
	["UseFlash"] 		= true,
	["UseExtraFlash"] 	= false,
	["UseRed"] 		= true,
	["UseCount"] 		= true,
	["CountScale"]  	= 11,
};

----------------------------------------------------------------------------------------
-- FUNCTIONS
----------------------------------------------------------------------------------------
-- ONxxxx

function ABI_OnLoad()

	if (this:GetParent()) then
		this:SetFrameLevel(this:GetParent():GetFrameLevel()+2);
		this.haveParent=true;
	else
		--ABI_Message("Error: "..this:GetName().." can't find his parent.");
		this.haveParent=false;
		this:Hide();
		return;
	end

	_,ABI_PlayerClass = UnitClass("player");

	this:RegisterEvent("ACTIONBAR_PAGE_CHANGED");
	this:RegisterEvent("ACTIONBAR_SLOT_CHANGED");
	this:RegisterEvent("ACTIONBAR_UPDATE_COOLDOWN");
	this:RegisterEvent("ACTIONBAR_UPDATE_USABLE");
	this:RegisterEvent("UPDATE_BONUS_ACTIONBAR");
	this:RegisterEvent("UPDATE_INVENTORY_ALERTS");
	this:RegisterEvent("PLAYER_AURAS_CHANGED");

	this:RegisterEvent("PET_BAR_UPDATE");
	this:RegisterEvent("PET_BAR_UPDATE_COOLDOWN");

	this:RegisterEvent("UNIT_COMBAT");

	local cooldownObject = getglobal(this:GetName().."Cooldown");
	cooldownObject:SetPoint("TOP",     this:GetParent():GetName(), "TOP"     );
	cooldownObject:SetPoint("BOTTOM",  this:GetParent():GetName(), "BOTTOM",0,8  );
	--cooldownObject:SetPoint("TOPRIGHT",    this:GetParent():GetName(), "TOPRIGHT"    );
	--cooldownObject:SetPoint("BOTTOMRIGHT", this:GetParent():GetName(), "BOTTOMRIGHT",0,16 );

	local countObject = getglobal(this:GetName().."Count");
	countObject:SetPoint("TOPLEFT",     this:GetParent():GetName(), "BOTTOMLEFT",0,16);
	countObject:SetPoint("TOPRIGHT",    this:GetParent():GetName(), "BOTTOMRIGHT",0,16);
	countObject:SetPoint("BOTTOMLEFT",  this:GetParent():GetName(), "BOTTOMLEFT");
	countObject:SetPoint("BOTTOMRIGHT", this:GetParent():GetName(), "BOTTOMRIGHT");

	local redObject = getglobal(this:GetName().."Red");
	redObject:SetAlpha(0.75);
	redObject:SetPoint("TOPLEFT",     this:GetParent():GetName(), "TOPLEFT"     );
	redObject:SetPoint("TOPRIGHT",    this:GetParent():GetName(), "TOPRIGHT"    );
	redObject:SetPoint("BOTTOMLEFT",  this:GetParent():GetName(), "BOTTOMLEFT"  );
	redObject:SetPoint("BOTTOMRIGHT", this:GetParent():GetName(), "BOTTOMRIGHT" );

	this.slotID 		= 0;
	this.cost		= 0;
	this.needUpdate		= true;
	this.active 		= false;
	this.type		= "normal";
	this.caster		= "player";
	this.costType		= nil;
	this.cooldownStart 	= 0;
	this.cooldownDuration 	= 0;
	this.shining  		= false;
	this.cooldowning	= false;
	this.useLife		= false;

	this.flashOn  = {
		["WOUND"] = {["player"]= false, ["target"]= false, },
		["MISS"]  = {["player"]= false, ["target"]= false, },
		["PARRY"] = {["player"]= false, ["target"]= false, },
		["BLOCK"] = {["player"]= false, ["target"]= false, },
		["DODGE"] = {["player"]= false, ["target"]= false, },
		["HEAL"]  = {["player"]= false, ["target"]= false, },
	};

	getglobal(this:GetName().."Count"):SetTextHeight(11);

end

function ABI_MainOnEvent()
	if ( event == "VARIABLES_LOADED") then
		if (ABI_SavedInfo["UseCooldown"]==nil) then
			ABI_SavedInfo["UseCooldown"]=true;
		end
		if (ABI_SavedInfo["UseFlash"]==nil) then
			ABI_SavedInfo["UseFlash"]=true;
		end
		if (ABI_SavedInfo["UseExtraFlash"]==nil) then
			ABI_SavedInfo["UseExtraFlash"]=false;
		end
		if (ABI_SavedInfo["UseRed"]==nil) then
			ABI_SavedInfo["UseRed"]=true;
		end
		if (ABI_SavedInfo["UseCount"]==nil) then
			ABI_SavedInfo["UseCount"]=true;
		end
		if (ABI_SavedInfo["CountScale"]==nil) then
			ABI_SavedInfo["CountScale"]=11;
		end
		return;
	end
end

function ABI_OnEvent()
	if ( event == "UNIT_COMBAT" ) then
		if ( ABI_SavedInfo["UseExtraFlash"]==true and this.flashOn[arg2] and this.flashOn[arg2][arg1] ) then
			ABI_StartShinning();
		end
		return;
	end
	if ( event == "ACTIONBAR_SLOT_CHANGED" ) then
		if ( arg1 == -1 or arg1 == this.slotID) then
			this.needUpdate=true;
		end
		return;
	end
	if ( event == "ACTIONBAR_PAGE_CHANGED" ) then
		this.needUpdate=true;
		return;
	end
	if ( event == "PLAYER_AURAS_CHANGED" ) then
		this.needUpdate=true;
		return;
	end
	if ( event == "UPDATE_BONUS_ACTIONBAR" ) then
		this.needUpdate=true;
		return;
	end
	if ( event == "UNIT_INVENTORY_CHANGED" ) then
		if ( arg1 == "player" ) then
			this.needUpdate=true;
		end
		return;
	end
	if ( event == "ACTIONBAR_UPDATE_USABLE") then
		this.needUpdate=true;
		return;
	end
	if ( event == "UPDATE_INVENTORY_ALERTS" ) then
		this.needUpdate=true;
		return;
	end
	if ( event == "ACTIONBAR_UPDATE_COOLDOWN" ) then
		this.needUpdate=true;
		return;
	end
	if ( event == "PET_BAR_UPDATE" ) then
		this.needUpdate=true;
		return;
	end
	if ( event == "PET_BAR_UPDATE_COOLDOWN" ) then
		this.needUpdate=true;
		return;
	end
end

function ABI_OnUpdate()
	if (this.haveParent==true) then
		local pagedID, type = ABI_GetPagedID();
		if (type == "petToken" or type == "error") then
			this.active = false;
		else
			if ( (this.needUpdate==true) or (this.slotID ~= pagedID) or (this.type ~= type) ) then
				this.slotID	= pagedID;
				this.type	= type;
				if (this.type == "pet") then
					this.caster = "pet";
				else
					this.caster = "player";
				end
				if ( HasAction(this.slotID) ) then
					this.active = true;
					ABI_UpdateCooldown();
					ABI_RefreshToolTipInfo();
				else
					this.active = false;
				end
			end
		end
		this.needUpdate	= false;
		ABI_RefreshCooldownDisplay();
		ABI_RefreshCountDisplay();
		ABI_RefreshRedDisplay();
		ABI_UpdateShinning();
	end
end

----------------------------------------------------------------------------------------
-- Updates

function ABI_UpdateCooldown()
	if ( this.active==true) then
		local cooldownObject  = getglobal(this:GetName().."Cooldown");
		local start, duration, enable;
		if (this:GetID()==ABI_SHAPEBAR) then
			start, duration, enable = GetShapeshiftFormCooldown(this.slotID);
		elseif (this:GetID()==ABI_PETEBAR) then
			start, duration, enable = GetPetActionCooldown(this.slotID);
		else
			start, duration, enable = GetActionCooldown(this.slotID);
		end
		if (start>0 and duration>0 and enable>0) then
			if ( (this.cooldowning) or (duration > 2.0) ) then
				this.cooldownStart	= start;
				this.cooldownDuration	= duration;
				this.cooldowning	= true;
			end
		else
			this.cooldowning = false;
		end
	else
		this.cooldowning = false;
	end
end

function ABI_RefreshCooldownDisplay()
	local cooldownObjectShort = getglobal(this:GetName().."CooldownShort"); cooldownObjectShort:Hide();
	local cooldownObject 	  = getglobal(this:GetName().."Cooldown"     ); cooldownObject:Hide();
	local cooldownObjectLong  = getglobal(this:GetName().."CooldownLong" ); cooldownObjectLong:Hide();
	if ( this.active==true and this.cooldowning==true ) then
		local remainingTime = ceil(( this.cooldownStart + this.cooldownDuration ) - GetTime());
		if ( remainingTime > 0 ) then
			if (ABI_SavedInfo["UseCooldown"]==true) then
				local formattedTime, durationTag = ABI_FormatTime(remainingTime);
				local currentCooldownObject = getglobal(this:GetName().."Cooldown"..durationTag);
				currentCooldownObject:SetText(formattedTime);
				currentCooldownObject:Show();
			end
		else
			if (ABI_SavedInfo["UseFlash"]==true) then
				ABI_StartShinning();
			end
			this.cooldowning = false;
		end
	end
end

function ABI_RefreshToolTipInfo()
	this.cost, this.abilityName, this.useLife, this.costType = ABI_GetTooltipInfo();
	if ( this.active==false or ABI_SavedInfo["UseCount"]==false ) then
		this.cost = 0;
	end
	if (this.abilityName==ABI_OVERPOWER_NAME) then
		this.flashOn  = {};
		this.flashOn  = {
			["DODGE"] = {["player"]= false, ["target"]= true, },
		};
	elseif (this.abilityName==ABI_REVENGE_NAME) then
		this.flashOn  = {};
		this.flashOn  = {
			["PARRY"] = {["player"]= true, ["target"]= false, },
			["BLOCK"] = {["player"]= true, ["target"]= false, },
			["DODGE"] = {["player"]= true, ["target"]= false, },
		};
	elseif (this.abilityName==ABI_RIPOSTE_NAME) then
		this.flashOn  = {};
		this.flashOn  = {
			["PARRY"] = {["player"]= true,  ["target"]= false, },
		};
	else
		this.flashOn  = {};
	end
end

function ABI_RefreshCountDisplay()
	local countObject = getglobal(this:GetName().."Count");
	if ( this.active==true and this.cost>0 and ABI_SavedInfo["UseCount"]==true ) then
		local count = 0;
		if (this.useLife==true) then							-- Use Life ?
			count = floor(UnitHealth(this.caster)/this.cost);
		elseif (this.costType~=nil and UnitPowerType(this.caster)==this.costType) then 	-- Does this spell use the current power type ?
			if (UnitPowerType(this.caster)==3) then 					-- Use Energy ?
				count = ceil( (this.cost - UnitMana(this.caster)) / 20 );
			else										-- Use Mana or Rage
				count = floor(UnitMana(this.caster)/this.cost);	
			end
		end
		if (count > 0) then
			countObject:SetTextHeight(ABI_SavedInfo["CountScale"]);
			countObject:SetText( count );
			countObject:Show();
		else
			countObject:Hide();
		end
	else
		countObject:Hide();
	end
end

function ABI_StartShinning()
	local shineObject = getglobal(this:GetName().."Shine");
	if (this.shining==false) then
		this.shining=true;
		shineObject:SetVertexColor(1.0,1.0,1.0,1.0);
		shineObject:SetHeight(ABI_SHINE_HEIGHT);
		shineObject:SetWidth(ABI_SHINE_WIDTH);
		shineObject:Show();
	end
end

function ABI_UpdateShinning()
	local shineObject = getglobal(this:GetName().."Shine");
	if (this.shining==true) then
		local alpha = shineObject:GetAlpha();
		shineObject:SetVertexColor(1.0,1.0,1.0,(alpha*0.95));
		if (alpha<0.1) then
			shineObject:Hide();
			this.shining=false;
		else
			shineObject:SetHeight(alpha*ABI_SHINE_HEIGHT);
			shineObject:SetWidth(alpha*ABI_SHINE_WIDTH);
		end
	end
end

function ABI_RefreshRedDisplay()
	local redObject = getglobal(this:GetName().."Red");
	if ( this.active==true and ABI_SavedInfo["UseRed"]==true and IsActionInRange(this.slotID)==0) then
		redObject:Show();
	else
		redObject:Hide();
	end
end

----------------------------------------------------------------------------------------
-- Slash Commands

function ABI_RegisterSlashCommands()
	SlashCmdList["ACTIONBARINFO"] = ABI_SlashCommand;
	SLASH_ACTIONBARINFO1 = "/abinfo"
	SLASH_ACTIONBARINFO2 = "/abi"
end

function ABI_SlashCommand(msg)
	msg = string.lower(msg);
	if ( string.find(msg, 'cooldown') ) then
		if (ABI_SavedInfo["UseCooldown"] == true) then
			ABI_SavedInfo["UseCooldown"] = false;
			ABI_Message(ABI_COOLDOWN_OFF);
		else
			ABI_SavedInfo["UseCooldown"] = true;
			ABI_Message(ABI_COOLDOWN_ON);
		end
	elseif ( string.find(msg, 'extraflash') ) then
		if (ABI_SavedInfo["UseExtraFlash"] == true) then
			ABI_SavedInfo["UseExtraFlash"] = false;
			ABI_Message(ABI_EXFLASH_OFF);
		else
			ABI_SavedInfo["UseExtraFlash"] = true;
			ABI_Message(ABI_EXFLASH_ON);
		end
	elseif ( string.find(msg, 'flash') ) then
		if (ABI_SavedInfo["UseFlash"] == true) then
			ABI_SavedInfo["UseFlash"] = false;
			ABI_Message(ABI_FLASH_OFF);
		else
			ABI_SavedInfo["UseFlash"] = true;
			ABI_Message(ABI_FLASH_ON);
		end
	elseif ( string.find(msg, 'red') ) then
		if (ABI_SavedInfo["UseRed"] == true) then
			ABI_SavedInfo["UseRed"] = false;
			ABI_Message(ABI_RED_OFF);
		else
			ABI_SavedInfo["UseRed"] = true;
			ABI_Message(ABI_RED_ON);
		end
	elseif ( string.find(msg, 'countsize') ) then
		local _, _, scale = string.find(msg,"countsize (%d+)");
		scale = tonumber(scale);
		if (scale<8) then
			ABI_SavedInfo["CountScale"]=8;
		elseif (scale>16) then
			ABI_SavedInfo["CountScale"]=16;
		else
			ABI_SavedInfo["CountScale"]=scale;
		end
		ABI_Message(ABI_COUNT_SCALE_CHANGED..ABI_SavedInfo["CountScale"]);
	elseif ( string.find(msg, 'count') ) then
		if (ABI_SavedInfo["UseCount"] == true) then
			ABI_SavedInfo["UseCount"] = false;
			ABI_Message(ABI_COUNT_OFF);
		else
			ABI_SavedInfo["UseCount"] = true;
			ABI_Message(ABI_COUNT_ON);
		end
	else
		local i;
		for i=1, table.getn(ABI_HELP) do
			ABI_SimpleMessage(ABI_HELP[i]);
		end
	end
end

----------------------------------------------------------------------------------------
-- Misc

function ABI_GetTooltipInfo()

	if (this.type=="pet") then
		ABITooltip:SetPetAction(this.slotID);
	elseif (this.type=="shapeshift") then
		ABITooltip:SetShapeshift(this.slotID);
	elseif (this.type=="normal") then
		ABITooltip:SetAction(this.slotID);
	else
		return 0,"",nil;
	end
	local abilityNameText = ABITooltipTextLeft1:GetText();
	local costText = ABITooltipTextLeft2:GetText();

	if (abilityNameText == nil) then
		abilityNameText="";
	end
	if (costText == nil) then
		return 0, abilityNameText, nil;
	end

	local i=0;
	local _,cost;
	while (ABI_Cost[i]~=nil) do
		_, _, cost = string.find(costText,ABI_Cost[i]["text"]);
		cost = tonumber(cost);
		if (cost ~= nil and cost>0) then
			return cost, abilityNameText, ABI_Cost[i]["isLife"], ABI_Cost[i]["costType"];
		end
		i=i+1;
	end
	return 0, abilityNameText, nil;

end

function ABI_GetPagedID()
	local ID = this:GetID();
	local parentID = this:GetParent():GetID();

	if (ID==ABI_NORMALBAR) then					-- ID of the parent is equal to the slot ID 
		return parentID, "normal";
	elseif (ID==ABI_BONUSBAR) then					-- Special case for the ActionButton and BonusActionButton 
		if ( this:GetParent().isBonus and CURRENT_ACTIONBAR_PAGE==1 ) then
			local offset = GetBonusBarOffset();
			if ( offset == 0 and BonusActionBarFrame and BonusActionBarFrame.lastBonusBar ) then
				offset = BonusActionBarFrame.lastBonusBar;
			end
			return parentID + ((NUM_ACTIONBAR_PAGES+offset-1)*NUM_ACTIONBAR_BUTTONS), "normal";
		else
			return parentID + ((CURRENT_ACTIONBAR_PAGE-1)*NUM_ACTIONBAR_BUTTONS), "normal";
		end
	elseif (ID>=ABI_MULTIBAR_FIRST and ID<=ABI_MULTIBAR_LAST) then	-- Special case for the MultiBarxxxxButton
		return parentID + ((ID-1)*NUM_ACTIONBAR_BUTTONS), "normal";
	elseif (ID==ABI_PETBAR) then					-- Special case for the PetActionButton
		if (this:GetParent().isToken) then
			return nil,"petToken";
		else
			return parentID,"pet";
		end
	elseif (ID==ABI_SHAPEBAR) then					-- Special case for the ShapeshiftButton
		return parentID,"shapeshift";
	else
		return nil, "error";
	end
end


function ABI_FormatTime(time)
	if (time>=3600) then
		return ( math.floor((time / 3600)+0.5).."h" ), "Long";
	elseif (time>=60) then
		return ( math.floor((time / 60)+0.5).."m" ), "Long";
	elseif (time>5) then
		return time, "";
	else
		return time, "Short";
	end
end

----------------------------------------------------------------------------------------
-- Debug

function ABI_Message(text)
	DEFAULT_CHAT_FRAME:AddMessage(ABI_MODNAME.." : "..text,1,1,0);
end

function ABI_SimpleMessage(text)
	DEFAULT_CHAT_FRAME:AddMessage(text,1,1,0);
end

function ABI_MessageOnce(text)
	if (this:GetName()=="ABIBlizzardBars1") then
		DEFAULT_CHAT_FRAME:AddMessage(ABI_MODNAME..": "..text,1,0,0);
	end
end
