--------------------------------------------------------------------------
--DurabilityStatus.lua
--------------------------------------------------------------------------
--[[
	DurabilityStatus
		Lets you know your current percentage and cost

	Original author: Derkyle http://www.manaflux.com
	Converted to Cosmos and maintained by: zespri <zespriwow@gmail.com>

	$Id: DurabilityStatus.lua 4157 2006-10-13 20:12:04Z geowar $
	$Rev: 4157 $
	$LastChangedBy: geowar $
	$Date: 2006-10-13 15:12:04 -0500 (Fri, 13 Oct 2006) $
]]--

local DURABILITYSTATUS_NAME 		= "Durability Status"
local DURABILITYSTATUS_VERSION 		= "1.7z"
local DURABILITYSTATUS_LAST_UPDATED	= "August 14, 2006"
local DURABILITYSTATUS_AUTHOR 		= "zespri"
local DURABILITYSTATUS_EMAIL		= "zespri@cosmosui.org"
local DURABILITYSTATUS_WEBSITE		= "http://www.wowwiki.com/DurabilityStatus"

local tmrCount;
local DSValues_Armor = { value=0, max=0, cost=0 };
local DSValues_Inven = { value=0, max=0, cost=0 };
local DS_CurrPercent = 100;

local DurStatus_Slots = {
	{ name = INVTYPE_HEAD, slot = "Head" },
	{ name = INVTYPE_SHOULDER, slot = "Shoulder" },
	{ name = INVTYPE_CHEST, slot = "Chest" },
	{ name = INVTYPE_WAIST, slot = "Waist" },
	{ name = INVTYPE_LEGS, slot = "Legs" },
	{ name = INVTYPE_FEET, slot = "Feet" },
	{ name = INVTYPE_WRIST, slot = "Wrist" },
	{ name = INVTYPE_HAND, slot = "Hands" },
	{ name = INVTYPE_WEAPONMAINHAND, slot = "MainHand" },
	{ name = INVTYPE_WEAPONOFFHAND, slot = "SecondaryHand" },
	{ name = INVTYPE_RANGED, slot = "Ranged" },
	{ name = INVENTORY_TOOLTIP },
}


---------------------------------------------------
-- DurabilityStatus_OnLoad
---------------------------------------------------
function DurabilityStatus_OnLoad()

	if (Khaos and DurabilityStatus_Register_Khaos) then
		DurabilityStatus_Register_Khaos()
	end

	this:RegisterEvent("VARIABLES_LOADED");
	--bagupdate
	this:RegisterEvent("PLAYER_DEAD");--bagupdate
	this:RegisterEvent("PLAYER_UNGHOST"); --bagupdate
	this:RegisterEvent("UPDATE_INVENTORY_ALERTS"); --update inventory
	this:RegisterEvent("PLAYER_LEAVING_WORLD");
	this:RegisterEvent("PLAYER_ENTERING_WORLD");
	--merchant
	this:RegisterEvent("MERCHANT_SHOW");
	this:RegisterEvent("MERCHANT_CLOSED");

	--this:RegisterEvent("PLAYER_REGEN_ENABLED");--bagupdate


	-- Register our slash command
	---------------------------------------------------
	SLASH_DURABILITYSTATUS1 = "/durstatus";
	SlashCmdList["DURABILITYSTATUS"] = DurabilityStatus_SlashCommand;


	if( DEFAULT_CHAT_FRAME and not Khaos) then
		DEFAULT_CHAT_FRAME:AddMessage("|c0077C249Derkyle's DurabilityStatus Ver "..DURABILITYSTATUS_VERSION..".|r |c00FFFFFF/durstatus|r");
	end

end



---------------------------------------------------
-- DurabilityStatus_OnEvent
---------------------------------------------------
function DurabilityStatus_OnEvent(event)

	if (event == "VARIABLES_LOADED") then

		if(not DurStatusOpt) then DurStatusOpt =
		{
			showMerchant=true,
			showReport=true,
			showWindow=true,
			lockWindow=false,
			showAverage=false
		}; end
		if(DurStatusOpt.showWindow ) then DS_Window:Show(); else DS_Window:Hide(); end

		DS_Window:SetUserPlaced(true);
		DurabilityStatus_BagUpdate();

	end

	if (event == "PLAYER_ENTERING_WORLD" or event == "UPDATE_INVENTORY_ALERTS" or event == "PLAYER_UNGHOST" or event == "PLAYER_DEAD") then

		--update quickly if at a merchant
		if(CanMerchantRepair() and DS_CurrPercent < 100) then
			DurabilityStatus_Core.bagupdate = 0;
		else
			DurabilityStatus_Core.bagupdate = 5;
		end

	end

	if (event == "PLAYER_ENTERING_WORLD") then
		this:RegisterEvent("UPDATE_INVENTORY_ALERTS");
		return;
	end

	if (event == "PLAYER_LEAVING_WORLD") then
		this:UnregisterEvent("UPDATE_INVENTORY_ALERTS");
		return;
	end

	if(event == "MERCHANT_SHOW") then

		if(DurStatusOpt.showMerchant) then

			DurabilityStatus_Core.bagupdate = 0;
			DurabilityStatus_ShowMerchantRepair();

		end

	elseif(event == "MERCHANT_CLOSED") then

		DS_Window_Repair:Hide();
	end

end


---------------------------------------------------
-- DurabilityStatus_SlashCommand
---------------------------------------------------
function DurabilityStatus_SlashCommand(msg)


	if (msg == nil) then

		return nil;
	end


	local num, offset, command, args = string.find (msg, "^(%w+)%s*(.*)$");

	if (command == nil) then

		DurabilityStatus_PrintHelp();
		return nil;
	end

	if (string.lower(command) == "merchant" ) then
		DurabilityStatus_Command_Toggle(args, "showMerchant")
		return;
	end

	if (string.lower(command) == "window" ) then
		DurabilityStatus_Command_Toggle(args, "showWindow",
			function(state)
				if (state) then
					DS_Window:Show()
				else
					DS_Window:Hide()
				end;
			end
		)
		return;
	end

	if (string.lower(command) == "report" ) then
		DurabilityStatus_Command_Toggle(args, "showReport")
		return;
	end

	if (string.lower(command) == "lock" ) then
		DurabilityStatus_Command_Toggle(args, "lockWindow")
		return;
	end

	if (string.lower(command) == "overall" ) then
		DurabilityStatus_Command_Toggle(args, "showAverage", DurabilityStatus_BagUpdate)
		return;
	end

	DurabilityStatus_PrintHelp();
end


---------------------------------------------------
-- DurabilityStatus_Command_Toggle
---------------------------------------------------
function DurabilityStatus_Command_Toggle(args, switch, func)
	local newValue;
	if (string.len(args) == 0) then
		newValue = not DurStatusOpt[switch];
	elseif( string.lower(args) == "on" ) then
		newValue = true;
	elseif( string.lower(args) == "off" ) then
		newValue = false;
	else
		DEFAULT_CHAT_FRAME:AddMessage(DURABILITYSTATUS_INVALID_ARGUMENT);
		return;
	end
	DurStatusOpt[switch] = newValue;

	if (Khaos) then
		Khaos.setSetKeyParameter("DurabilityStatus", switch, "checked", DurStatusOpt[switch]);
		Khaos.refresh();
	end

	if ( func ) then
		func(DurStatusOpt[switch]);
	end
end


---------------------------------------------------
-- DurabilityStatus_PrintHelp
---------------------------------------------------
function DurabilityStatus_PrintHelp()
	if( DEFAULT_CHAT_FRAME ) then
		DEFAULT_CHAT_FRAME:AddMessage("|c0077C249DurabilityStatus: |c00FFFFFF/durstatus merchant on/off|r");
		DEFAULT_CHAT_FRAME:AddMessage("|c0077C249DurabilityStatus: |c00FFFFFF/durstatus window on/off|r");
		DEFAULT_CHAT_FRAME:AddMessage("|c0077C249DurabilityStatus: |c00FFFFFF/durstatus lock on/off|r");
		DEFAULT_CHAT_FRAME:AddMessage("|c0077C249DurabilityStatus: |c00FFFFFF/durstatus report on/off|r");
		DEFAULT_CHAT_FRAME:AddMessage("|c0077C249DurabilityStatus: |c00FFFFFF/durstatus overall on/off|r");
	end
end



---------------------------------------------------
-- DurabilityStatus_OnUpdate
---------------------------------------------------
function DurabilityStatus_OnUpdate(elapsed)

	--BAG_UPDATE
	if(DurabilityStatus_Core.bagupdate) then

		--update the lapse
		DurabilityStatus_Core.bagupdate = DurabilityStatus_Core.bagupdate - elapsed;

		--check if the timer ran out
		if ( DurabilityStatus_Core.bagupdate <= 0 ) then

			DurabilityStatus_BagUpdate();
			DurabilityStatus_Core.bagupdate = nil;

		end

	end

end



---------------------------------------------------
-- DurabilityStatus_BagUpdate
---------------------------------------------------
function DurabilityStatus_BagUpdate()

	--if player is not at merchant and is in combat then update slowly
	--if (tmrCount and GetTime() - tmrCount < 6 and event == "UPDATE_INVENTORY_ALERTS" and not CanMerchantRepair() and UnitAffectingCombat("player")) then
	--	return nil;
	--end

	--update count
	--tmrCount = GetTime();

	--inventory
	DSValues_Inven.value = 0;
	DSValues_Inven.max = 0;
	DSValues_Inven.cost = 0;


	--if we are a hunter then only do inventory if we aren't in combat
	--if(UnitClass("player") == "Hunter" and not UnitAffectingCombat("player")) then

		for bag = 0, 4 do
			for slot = 1, GetContainerNumSlots(bag) do

				local sPercent, value, max, cost = DurabilityStatus_GetStatus(slot, bag);

				if (cost ~= nil) then
					DSValues_Inven.value = DSValues_Inven.value + value;
					DSValues_Inven.max = DSValues_Inven.max + max;
					DSValues_Inven.cost = DSValues_Inven.cost + cost;
				end
			end
		end

	--end


	--ARMOR
	DSValues_Armor.value = 0;
	DSValues_Armor.max = 0;
	DSValues_Armor.cost = 0;

	for i = 1, 11 do

		local sPercent, value, max, cost = DurabilityStatus_GetStatus(i);

		if (cost ~= nil) then
			if DurStatusOpt.showAverage then
				DSValues_Armor.value = DSValues_Armor.value + value;
				DSValues_Armor.max = DSValues_Armor.max + max;
			else
				local current = DurabilityStatus_GetStatusPercent(value, max)
				local minimum = DurabilityStatus_GetStatusPercent(DSValues_Armor.value, DSValues_Armor.max)
				if (current < minimum) or (DSValues_Armor.max == 0) then
					DSValues_Armor.value = value;
					DSValues_Armor.max = max;
				end
			end
			DSValues_Armor.cost = DSValues_Armor.cost + cost;
		end

	end


	--update the percentage
	DurabilityStatus_UpdatePercent();

	--update the merchant window
	if(DS_Window_Repair:IsVisible()) then
		DurabilityStatus_ShowMerchantRepair();
	end

end


---------------------------------------------------
-- DurabilityStatus_GetStatus
---------------------------------------------------
function DurabilityStatus_GetStatus(index, bag)
	local val = 0;
	local max = 0;
	local cost = 0;
	local hasItem, repairCost

	DSCHKTT:SetOwner(WorldFrame, "ANCHOR_NONE");

	if (bag) then
		local _, lRepairCost = DSCHKTT:SetBagItem(bag, index);

		repairCost = lRepairCost;
		hasItem = 1;
	else
		local slotName = DurStatus_Slots[index].slot .. "Slot";

		local id = GetInventorySlotInfo(slotName);
		local lHasItem, _, lRepairCost = DSCHKTT:SetInventoryItem("player", id);
		hasItem = lHasItem;
		repairCost = lRepairCost;
	end

	if (hasItem) then
		if (repairCost) then
			cost = repairCost;
		end

		for i = 1, 30 do
			local field = getglobal("DSCHKTTTextLeft" .. i);
			if (field ~= nil) then
				local text = field:GetText();
				if (text) then
					-- find durability
					local _, _, f_val, f_max = string.find(text, DURABILITYSTATUS_TEXTCHK);

					if (f_val) then
						val = tonumber(f_val);
						max = tonumber(f_max);
					end
				end
			end

		end

	end

	DSCHKTT:Hide();
	return DurabilityStatus_GetStatusPercent(val, max), val, max, cost;

end


---------------------------------------------------
-- DurabilityStatus_GetStatusPercent
---------------------------------------------------
function DurabilityStatus_GetStatusPercent(val, max)
	if (max > 0) then
		return (val / max);
	end
	return 1.0;
end




---------------------------------------------------
-- DurabilityStatus_UpdatePercent
---------------------------------------------------
function DurabilityStatus_UpdatePercent()
	local green = GREEN_FONT_COLOR;
	local yellow = NORMAL_FONT_COLOR;
	local red = RED_FONT_COLOR;

	local percent = DurabilityStatus_GetStatusPercent(DSValues_Armor.value, DSValues_Armor.max);

	local color = {};

	if (percent == 1.0) then
		color = green;
	elseif (percent == 0.5) then
		color = yellow;
	elseif (percent == 0.0) then
		color = red;
	elseif (percent > 0.5) then
		local pct = (1.0 - percent) * 2;
		color.r =(yellow.r - green.r)*pct + green.r;
		color.g = (yellow.g - green.g)*pct + green.g;
		color.b = (yellow.b - green.b)*pct + green.b;
	elseif (percent < 0.5) then
		local pct = (0.5 - percent) * 2;
		color.r = (red.r - yellow.r)*pct + yellow.r;
		color.g = (red.g - yellow.g)*pct + yellow.g;
		color.b = (red.b - yellow.b)*pct + yellow.b;
	end

	--make sure we don't go overboard
	if( ceil(percent*100) > 100) then percent = 100; else percent = ceil(percent*100); end

	DS_CurrPercent = percent;

	DS_WindowText:SetText(percent.."%");
	DS_WindowText:SetTextColor(color.r, color.g, color.b);

end


---------------------------------------------------
-- DurabilityStatus_ShowTooltip
---------------------------------------------------
function DurabilityStatus_ShowTooltip()

	GameTooltip_SetDefaultAnchor(GameTooltip, UIParent);
	GameTooltip:AddLine("|c0077C249" .. DURABILITYSTATUS_CONFIG_HEADER .. "|r");
	GameTooltip:AddDoubleLine("|c00FFFFFF"..DURABILITYSTATUS_INVEN.."|r",DurabilityStatus_GetMoneyString(DSValues_Inven.cost),1,1,1,1,1,1);
	GameTooltip:AddDoubleLine("|c00FFFFFF"..DURABILITYSTATUS_ARMOR.."|r",DurabilityStatus_GetMoneyString(DSValues_Armor.cost),1,1,1,1,1,1);
	GameTooltip:AddLine(" ");
	GameTooltip:AddDoubleLine("|c00FFFFFF"..DURABILITYSTATUS_BOTH.."|r", DurabilityStatus_GetMoneyString( (DSValues_Inven.cost + DSValues_Armor.cost ) ),1,1,1,1,1,1);
	GameTooltip:Show();

end




---------------------------------------------------
-- DurabilityStatus_ReturnSplitMoney
---------------------------------------------------
function DurabilityStatus_ReturnSplitMoney(sMoney)

	--convert the long money value into seperate variables
	local gold = floor(sMoney / (COPPER_PER_SILVER * SILVER_PER_GOLD));
	-- local silver = floor((sMoney - (gold * COPPER_PER_SILVER * SILVER_PER_GOLD)) / COPPER_PER_SILVER);
	local silver = floor(sMoney / COPPER_PER_SILVER) % SILVER_PER_GOLD;
	local copper = sMoney % COPPER_PER_SILVER;

	return gold, silver, copper;
end



---------------------------------------------------
-- DurabilityStatus_GetMoneyString
---------------------------------------------------
function DurabilityStatus_GetMoneyString(sAmt)

	if(not sAmt or tonumber(sAmt) == 0 ) then return "0"; end

	--get the split amount
	local gold, silver, copper = DurabilityStatus_ReturnSplitMoney(sAmt);

	--add zero's to work with
	if(not gold) then gold = 0; end
	if(not silver) then silver = 0; end
	if(not copper) then copper = 0; end

	local sStoreString = "";

	-----------------------------------
	--gold
	if(gold ~= 0) then

		sStoreString = string.format("|c00FFFFFF%s|r|c00E2CD54g|r ", gold);
	end

	--silver
	if(gold ~= 0 or silver ~= 0) then

		--add double zero's
		if(silver == 0) then
			sStoreString = sStoreString..string.format("|c00FFFFFF%s|r|c00AEAEAEs|r ", "00");
		else
			sStoreString = sStoreString..string.format("|c00FFFFFF%s|r|c00AEAEAEs|r ", silver);
		end

	end

	--copper
	if(gold ~= 0 or silver ~= 0 or  copper ~= 0) then

		--add double zero's
		if(copper == 0) then
			sStoreString = sStoreString..string.format("|c00FFFFFF%s|r|c00D7844Dc|r", "00");
		else
			sStoreString = sStoreString..string.format("|c00FFFFFF%s|r|c00D7844Dc|r", copper);
		end

	end
	-----------------------------------


	return sStoreString;


end





---------------------------------------------------
-- DurabilityStatus_ShowMerchantRepair
---------------------------------------------------
function DurabilityStatus_ShowMerchantRepair()

	if (CanMerchantRepair()) then

		if(DSValues_Inven.cost > 0 or DSValues_Armor.cost > 0) then

			DS_Window_RepairTextInven_Cost:SetText(DurabilityStatus_GetMoneyString(DSValues_Inven.cost));
			DS_Window_RepairTextArmor_Cost:SetText(DurabilityStatus_GetMoneyString(DSValues_Armor.cost));
			DS_Window_RepairTextBoth_Cost:SetText(DurabilityStatus_GetMoneyString( (DSValues_Inven.cost + DSValues_Armor.cost ) ));


			local userCash     = GetMoney();

			--check for money
			if(DSValues_Inven.cost <= userCash and DSValues_Inven.cost > 0) then
				DS_Window_RepairInvenButton:Enable();
			else
				DS_Window_RepairInvenButton:Disable();
			end

			--check for money
			if(DSValues_Armor.cost <= userCash and DSValues_Armor.cost > 0) then
				DS_Window_RepairArmorButton:Enable();
			else
				DS_Window_RepairArmorButton:Disable();
			end


			--check for money
			if( DSValues_Inven.cost > 0 and DSValues_Armor.cost > 0) then
				if ( (DSValues_Inven.cost + DSValues_Armor.cost) <= userCash and (DSValues_Inven.cost + DSValues_Armor.cost) > 0) then
					DS_Window_RepairBothButton:Enable();
				else
					DS_Window_RepairBothButton:Disable();
				end
			else
				DS_Window_RepairBothButton:Disable();
			end


			DS_Window_Repair:Show();

		end

	end


end


---------------------------------------------------
-- DurabilityStatus_RepairIventory
---------------------------------------------------
function DurabilityStatus_RepairIventory()

	local userCash     = GetMoney();

	--check that we have cash
	if(DSValues_Inven.cost <= userCash and DSValues_Inven.cost > 0) then

		ShowRepairCursor();

		local bag, slot;

		for bag = 0,4,1 do

			for slot = 1, GetContainerNumSlots(bag) do

				local _, repairCost = DSCHKTT:SetBagItem(bag,slot);

				if (repairCost and repairCost > 0) then

					PickupContainerItem(bag,slot);
				end
			end
		end

		HideRepairCursor();

	end


	if( DurStatusOpt.showReport and DEFAULT_CHAT_FRAME ) then
		DEFAULT_CHAT_FRAME:AddMessage("|cfff5f530" .. DURABILITYSTATUS_INVENTORY_COST .. ": [" .. DurabilityStatus_GetMoneyString(DSValues_Inven.cost) .. "|cfff5f530].|r");
	end

	DurabilityStatus_Core.bagupdate = 0;

end


---------------------------------------------------
-- DurabilityStatus_RepairBoth
---------------------------------------------------
function DurabilityStatus_RepairBoth()

	local userCash     = GetMoney();

	if(DSValues_Armor.cost + DSValues_Inven.cost <= userCash and DSValues_Armor.cost + DSValues_Inven.cost > 0) then

		RepairAllItems();

	end

	if( DurStatusOpt.showReport and DEFAULT_CHAT_FRAME ) then
		DEFAULT_CHAT_FRAME:AddMessage("|cfff5f530" .. DURABILITYSTATUS_BOTH_COST .. ": [" .. DurabilityStatus_GetMoneyString(DSValues_Armor.cost + DSValues_Inven.cost) .. "|cfff5f530].|r");
	end

	DurabilityStatus_Core.bagupdate = 0;

end


---------------------------------------------------
-- DurabilityStatus_RepairEquipment
---------------------------------------------------
function DurabilityStatus_RepairEquipment()

	local userCash     = GetMoney();

	if(DSValues_Armor.cost <= userCash and DSValues_Armor.cost > 0) then

		ShowRepairCursor();

		for i = 1, 11 do

			local slotName = DurStatus_Slots[i].slot .. "Slot";

			local id = GetInventorySlotInfo(slotName);
			local _, _, repairCost = DSCHKTT:SetInventoryItem("player", id);

			if (repairCost and repairCost > 0) then

				PickupInventoryItem(id);
			end

		end

		HideRepairCursor();
	end

	if( DurStatusOpt.showReport and DEFAULT_CHAT_FRAME ) then
		DEFAULT_CHAT_FRAME:AddMessage("|cfff5f530" .. DURABILITYSTATUS_ARMOR_COST .. ": [" .. DurabilityStatus_GetMoneyString(DSValues_Armor.cost) .. "|cfff5f530].|r");
	end

	DurabilityStatus_Core.bagupdate = 0;

end

