-- Constants 

-- GLOBALS --    
local AD_BaseFrame = CreateFrame("Frame", "AD_BaseFrame");
local AD_WaitFrame = CreateFrame("Frame","AD_WaitFrame", AD_BaseFrame);
local AD_TooltipFrame = nil;
local ItemAdded;
local DelayLeft = nil;



-- AutoDelete Addon OnLoad Event
--   
function AD_OnLoad(self)
	SlashCmdList["AUTODELETE"] = AD_SlashCommand;

	ItemAdded = {};
	ItemAdded[0] = false;
	ItemAdded[1] = false;
	ItemAdded[2] = false;
	ItemAdded[3] = false;
	ItemAdded[4] = false;
	
	AD_WaitFrame:SetScript("onUpdate", AD_WaitOnUpdate);
end

function AD_VariablesLoaded()
	if AD_Settings == nil then
		AD_Settings = {};
		AD_Settings.ShowDeletes = true;
		AD_Settings.DeleteDelay = 2;
		AD_Settings.WaitOnFull = true;
		AD_Settings.FullMark = 5;
	end

	if AD_DelList == nil then
		AD_DelList = {6530};
	end
	
	-- backwards compatable code:
	if AD_Settings.DeleteDelay == nil then
		AD_Settings.DeleteDelay = 1;
		AD_Settings.WaitOnFull = false;
		AD_Settings.FullMark = 5;
	end
end




-- Registered Events
AD_BaseFrame:RegisterEvent("PLAYER_ENTERING_WORLD");
AD_BaseFrame:RegisterEvent("ITEM_PUSH");
--AD_BaseFrame:RegisterEvent("BAG_UPDATE");
AD_BaseFrame:RegisterEvent("VARIABLES_LOADED");


-- AutoDelete Addon Event Handler
--   
function AD_EventHandler(self, event, arg1, arg2, ...)

--if arg1 == nil then
-- arg1 = "";
--end
--if arg2 == nil then
-- arg2 = "";
--end
--ChatFrame1:AddMessage("EVENT::" .. event .. "::" .. arg1 .. "::" .. arg2);
	
	if event == "ITEM_PUSH" then
--ChatFrame1:AddMessage("ITEM_PUSH:arg1:" .. arg1);
		DelayLeft = AD_Settings.DeleteDelay;
		if arg1 == 0 then
			--AD_Wait(0.5, AD_ScanBag, 0);
			ItemAdded[0] = true;
		elseif arg1 >= 20 and arg1 <= 22 then
			--AD_Wait(0.5, AD_ScanBag, arg1 - 19);
			ItemAdded[arg1 - 19] = true;
		end
--	elseif event == "BAG_UPDATE" then
--ChatFrame1:AddMessage("BAG_UPDATE:arg1:" .. arg1);
--		if ItemAdded[arg1] == true then
--			ItemAdded[arg1] = false;
--			AD_ScanBag(arg1);
--		end
	elseif event == "PLAYER_ENTERING_WORLD" then
		AD_OnLoad(self);
	elseif event == "VARIABLES_LOADED" then
		AD_VariablesLoaded();
	end
end
AD_BaseFrame:SetScript("OnEvent", AD_EventHandler);




-- AutoDelete Addon Slash Commands --
SLASH_AUTODELETE1, SLASH_AUTODELETE2 = "/ad", "/autodelete";

-- AutoDelete Addon Slash Command Handler
--
function AD_SlashCommand(msg, editbox)
	local cmd, cmdEnd;
	_, cmdEnd, cmd = string.find(msg, "(%a+) ?");

	if cmd ~= nil then
		cmd = string.lower(cmd);
--ChatFrame1:AddMessage(cmd);

		if cmd == "showdeletes" then
			if AD_Settings.ShowDeletes then
				AD_Settings.ShowDeletes = false;
ChatFrame1:AddMessage("Now hiding delete messages in chat.");
			else
				AD_Settings.ShowDeletes = true;
ChatFrame1:AddMessage("Now showing delete messages in chat.");
			end
		elseif cmd == "add" then
			AD_AddItem(string.sub(msg, cmdEnd + 1));  
		elseif cmd == "remove" then
			AD_RemoveItem(string.sub(msg, cmdEnd + 1));
		elseif cmd == "clearlist" then
ChatFrame1:AddMessage("All auto-deleted items have been removed from the list.");
			AD_DelList = {};
		elseif cmd == "deletedelay" then
			local delay;
			_,_, delay = string.find(string.sub(msg, cmdEnd + 1), "(%d+)");
			if delay == nil then
				AD_ChatUsage();
				return;
			end
			delay = delay / 1000;
			AD_Settings.DeleteDelay = delay;
ChatFrame1:AddMessage("Bags will be checked ".. delay*1000 .."ms after an item is looted.");  
		elseif cmd == "waitonfull" then
			if AD_Settings.WaitOnFull then
				AD_Settings.WaitOnFull = false;  
ChatFrame1:AddMessage("Bags will be checked after every item loot.");
			else
				AD_Settings.WaitOnFull = true;
ChatFrame1:AddMessage("Bags will only be checked when there are less than (FullMark) spaces free left.");
			end	     
		elseif cmd == "fullmark" then
			local newFull;
			_,_, newFull = string.find(string.sub(msg, cmdEnd + 1), "(%d+)");
			if newFull == nil then
				AD_ChatUsage();
				return;
			end
			AD_Settings.FullMark = tonumber(newFull);  
ChatFrame1:AddMessage("FullMark now set to "..newFull..".");
		elseif cmd == "showlist" then
			if #AD_DelList == 0 then
ChatFrame1:AddMessage("Auto-Delete List is empty.");
			else
				if AD_TooltipFrame == nil then
					AD_TooltipFrame = CreateFrame("GameTooltip", "AD_TooltipFrame", nil, "GameTooltipTemplate"); 
					AD_TooltipFrame:SetOwner(WorldFrame, "ANCHOR_NONE"); 
				end    
				local itemLinks = "";
				local newLink;        
				for i=1, #AD_DelList do
					AD_TooltipFrame:ClearLines();
					AD_TooltipFrame:SetHyperlink("item:" .. AD_DelList[i] .. ":0:0:0:0:0:0:0");
					_, newLink = AD_TooltipFrame:GetItem();
					itemLinks = itemLinks .. " " .. newLink;
				end
ChatFrame1:AddMessage("Items listed below will all be deleted as they are picked up automatically.");
ChatFrame1:AddMessage(itemLinks);
			end
		else --(show usage options)
			AD_ChatUsage();
		end
	else --(no command show usage options)
		AD_ChatUsage();
	end
end



-- AutoDelete Addon Chat Usage
-- Prints to chat the commands users can type in to use this addon.
function AD_ChatUsage()
ChatFrame1:AddMessage("AutoDelete slash command options:");
ChatFrame1:AddMessage("/ad add [item link]");
ChatFrame1:AddMessage("/ad remove [item link]");
ChatFrame1:AddMessage("/ad showlist");
ChatFrame1:AddMessage("/ad showdeletes");
ChatFrame1:AddMessage("/ad clearlist");
ChatFrame1:AddMessage("/ad deletedelay [delay (in ms)]");
ChatFrame1:AddMessage("/ad waitonfull");
ChatFrame1:AddMessage("/ad fullmark [empty bag slots]");
ChatFrame1:AddMessage("");
ChatFrame1:AddMessage("Command:");
ChatFrame1:AddMessage("add [item link] - add the item linked to the auto-delete list.");
ChatFrame1:AddMessage("remove [item link] - removed the item linked from the auto-delete list.");
ChatFrame1:AddMessage("showlist - show all items on the auto-delete list in chat.");
ChatFrame1:AddMessage("showdeletes - (toggle) print to chat every time the addon auto-deletes an item.");
ChatFrame1:AddMessage("clearlist - clear the auto-delete list."); 
ChatFrame1:AddMessage("deletedelay [delay (in ms)] - the delay to wait to scan your bag(s) after you last loot in milli-seconds.");
ChatFrame1:AddMessage("waitonfull - (toggle) wait till your bags have less open slots than the full mark to delete items, otherwise just delete them as they enter your bag.");
ChatFrame1:AddMessage("fullmark [empty bag slots] - number of empty bag slots left before starting to seach for items that can be deleted.");
end




-- AutoDelete Addon Add Delete Item
-- Adds an item to the AD_DelList array or prints an error to the chat box if 
-- it's already in the AD_DelList array or there is an imput error
function AD_AddItem(ItemLink)
	local itemId, itemIndex;
	_,_, itemId = string.find(ItemLink, "item:(%d+)");

	if itemId == nil then
ChatFrame1:AddMessage("Please link the item you wish to the auto-delete list after the add command by shift-clicking it.");
	end

	itemId = tonumber(itemId);
	itemIndex = AD_Find(itemId);
	if AD_DelList[itemIndex] == itemId then
ChatFrame1:AddMessage(ItemLink .. " is already in the auto-delete list.");
	else
		table.insert(AD_DelList, itemIndex, itemId);
ChatFrame1:AddMessage(ItemLink .. " added to the auto-delete list.");
	end
end

-- AutoDelete Addon Remove Delete Item
-- Removes an item from the AD_DelList array or prints an error to the chat box
-- if it's not in the AD_DelList array or there is an imput error
function AD_RemoveItem(ItemLink)
	local itemId, itemIndex;
	_,_, itemId = string.find(ItemLink, "item:(%d+)");

	if itemId == nil then
ChatFrame1:AddMessage("Please link the item you wish from the auto-delete list after the add command by shift-clicking it.");
	end

	itemId = tonumber(itemId);
	itemIndex = AD_Find(itemId);
	if AD_DelList[itemIndex] == itemId then
		table.remove(AD_DelList, itemIndex);
ChatFrame1:AddMessage(ItemLink .. " removed from the auto-delete list.");
	else
ChatFrame1:AddMessage(ItemLink .. " not found in the auto-delete list.");
	end
end




-- AutoDelete Addon Find Function
-- Find the index of an item in our AD_DelList variable or return the next higest ItemId
function AD_Find(ItemId)
	return AD_RFind(ItemId, 1, #AD_DelList);
end




-- AutoDelete Addon Recursive Find Function
-- Ment to be called from AD_Find() function, the recursive part of the find function.
function AD_RFind(ItemId, starting, ending)
	if ending < starting then
		return starting;
	end

	local mid = math.floor((starting + ending)  / 2);

	if AD_DelList[mid] == ItemId then
		return mid;
	elseif AD_DelList[mid] > ItemId then
		ending = mid - 1;
	else --if AD_DelList[mid] < ItemId then
		starting = mid + 1;
	end	 

	return  AD_RFind(ItemId, starting, ending);
end





-- AutoDelete Addon Scan Bag
-- Scan and delete items in the bag as the delete list indicates
function AD_ScanBag(bagId, maxDeletes)
--ChatFrame1:AddMessage("AD_ScanBag(" .. bagId .. ") called... (" .. GetContainerNumSlots(bagId) .. " slots)");
	local itemLink, itemId;
	local totalDeletes = 0;
	
	local maxSlots = GetContainerNumSlots(bagId);
	if maxSlots == nil or maxSlots == 0 then
	    return 0;
	end

	for slotId = maxSlots, 1, -1 do
--ChatFrame1:AddMessage("checking slot " .. slotId .. "...");
		itemLink = GetContainerItemLink(bagId, slotId);
		if itemLink ~= nil then
--ChatFrame1:AddMessage("slot " .. slotId .. " contains " .. itemLink);

			_,_, itemId = string.find(itemLink, "item:(%d+)");
			itemId = tonumber(itemId);
			
--ChatFrame1:AddMessage("checking " .. itemLink .. "...");
			if AD_DelList[AD_Find(itemId)] == itemId then
				if AD_Settings.ShowDeletes then
ChatFrame1:AddMessage("deleting " .. itemLink .. "...");
				end
				PickupContainerItem(bagId, slotId);
				DeleteCursorItem();
				
				totalDeletes = totalDeletes + 1;
				
				if maxDeletes ~= nil and totalDeletes >= maxDeletes then
					return totalDeletes;
				end
			end
		end
	end
	
	return totalDeletes;
end


---------------------------------------------
-- My Wait Script

function AD_WaitOnUpdate(self, elapse)
	if DelayLeft == nil then
		return;
	end
	
	DelayLeft = DelayLeft - elapse;
	if DelayLeft <= 0 then
		DelayLeft = nil;
		
		local openCount = 0;
		if AD_Settings.WaitOnFull then
			for i=0, 4 do
				openCount = openCount + GetContainerNumFreeSlots(i);
			end
			
			if openCount <= AD_Settings.FullMark then
				local maxDeletes = AD_Settings.FullMark - openCount + 1;
				for bagId=4, 0, -1 do
				    if ItemAdded[bagId] then
					   	local deleted = AD_ScanBag(bagId, maxDeletes);

					   	if deleted == 0 then
							ItemAdded[bagId] = false;
						end

					   	maxDeletes = maxDeletes - deleted;
					   	if maxDeletes <= 0 then
					   		return;
					   	end
					end
				end
			end
		else --if AD_Settings.WaitOnFull == false then
			for i = 4, 0, -1 do
				if ItemAdded[i] then
					AD_ScanBag(i);
					ItemAdded[i] = false;
				end
			end
		end
	end
end


---------------------------------------------
-- WoWWiki Wait Script (thank you)

local waitTable = {};
local waitFrame = nil;

function AD_Wait(delay, func, ...)
  if(type(delay)~="number" or type(func)~="function") then
    return false;
  end
  if(waitFrame == nil) then
    waitFrame = CreateFrame("Frame","WaitFrame", UIParent);
    waitFrame:SetScript("onUpdate",function (self,elapse)
      local count = #waitTable;
      local i = 1;
      while(i<=count) do
        local waitRecord = tremove(waitTable,i);
        local d = tremove(waitRecord,1);
        local f = tremove(waitRecord,1);
        local p = tremove(waitRecord,1);
        if(d>elapse) then
          tinsert(waitTable,i,{d-elapse,f,p});
          i = i + 1;
        else
          count = count - 1;
          f(unpack(p));
        end
      end
    end);
  end
  tinsert(waitTable,{delay,func,{...}});
  return true;
end
