Petster.Feed = ZubanLib.Object:New{
	Frame = nil;
	Button = ZubanLib.Object:New{
		_callPetTexture = "Interface\\Icons\\Ability_Hunter_BeastCall";
		_mendPetTexture = "Interface\\Icons\\Ability_Hunter_MendPet";
		_castText = string.format("/cast [target=pet, dead] %s; [nopet] %s; [pet, combat] %s;",
				PetsterResources.Spells.RevivePet,
				PetsterResources.Spells.CallPet,
				PetsterResources.Spells.MendPet);
		_castTextShift = string.format("/cast [target=pet, dead] %s; [modifier:shift] %s; [nopet] %s; [pet, combat] %s;",
				PetsterResources.Spells.RevivePet,
				PetsterResources.Spells.RevivePet,
				PetsterResources.Spells.CallPet,
				PetsterResources.Spells.MendPet);
		_castTextAlt = string.format("/cast [target=pet, dead] %s; [pet, modifier:alt] %s; [nopet] %s; [pet, combat] %s;",
				PetsterResources.Spells.RevivePet,
				PetsterResources.Spells.DismissPet,
				PetsterResources.Spells.CallPet,
				PetsterResources.Spells.MendPet);
		_warnThreshold = 3;
		_petHappyAlpha = 0.3;
		_normalAlpha = 1;
		SecureButton = nil;
		SelectedFood = nil;
	};
};

function Petster.Feed:OnLoad()
	self.Frame = getglobal("PetsterFrame");
	
	if (not ZubanLib.Unit:IsHunter() and not ZubanLib.Unit:IsWarlock()) then
		self.Frame:Hide();
		return;
	end

	this:RegisterEvent("VARIABLES_LOADED");
	this:RegisterEvent("UNIT_HAPPINESS");
	this:RegisterEvent("PET_BAR_UPDATE");
	this:RegisterEvent("PLAYER_REGEN_ENABLED");
	this:RegisterEvent("PLAYER_REGEN_DISABLED");

	-- setup slash command
	SLASH_PETSTER1 = "/petster";
	SlashCmdList["PETSTER"] = function(command)
		self:OnCommand(command);
	end
	
	-- SavedVariablesPerCharacter
	PetsterPetFamilyState = {};

	PetsterButtonState = {
		Enabled = true;
		Scale = Petster.MoverTemplate._normalScale;
		Locked = false;
	};

	if (ZubanLib.Unit:IsWarlock()) then
		PetsterButtonState.Enabled = false;
	end
	
	--local anchor = CreateFrame("CheckButton", nil, UIParent, "MoverAnchorTemplate")
	--local button = CreateFrame("CheckButton", "FeedPetButton", anchor, "FeedPetButtonTemplate");
	--anchor:SetAttribute("anchorchild", button)
	--button:SetAttribute("type", "macro");
	--button:ClearAllPoints();
	--button:SetPoint("TOPLEFT", anchor, "BOTTOMRIGHT", -15, 15);
	--self.Button.SecureButton = button;
	--self.Mover.SecureAnchor = anchor;
		
	self.Button.SecureButton = getglobal("PetsterFeedPetButton");
	self.Button.SecureButton:SetAttribute("type", "macro");
	self.Button.SecureButton:SetAttribute("macrotext", self.Button._castText);
	self.Button.SecureButton:SetClampedToScreen(true);
	
	self.Mover:Initialize("PetsterMoverAnchor", "PetsterFrame");
	self.Mover.SecureAnchor:SetAttribute("anchorchild", self.Button.SecureButton);
end

function Petster.Feed:OnVariablesLoaded()
	-- handy iterator method
	PetsterPetFamilyState.ForEachSelectedFood = function(self, action)
		foreach (self,
			function(family, v)
				if (type(v) ~= "function" and v ~= nil and v.SelectedFood ~= nil) then
					action(family, v.SelectedFood);
				end
			end
		);
	end

	PetsterPetFamilyState.RemoveFood = function(self, family)
		--table.remove(self, family);
		self[family] = nil;
	end

	self:SetEnabled(PetsterButtonState.Enabled);
	self.Mover:SetLocked(PetsterButtonState.Locked);
	self.Mover:SetScale(PetsterButtonState.Scale);
	self:OnPetBarUpdate();

	Petster:Write(PetsterResources.Loaded);
end

function Petster.Feed:OnPetHappiness()
	local happiness = ZubanLib.Pet:Happiness();
	
	if (self.Button.SelectedFood == nil
		or ZubanLib.Player:AffectingCombat()
		or ZubanLib.Pet:AffectingCombat()
		or (not ZubanLib.Pet:Exists())
		or (not ZubanLib.Pet:IsHappy()
			and ZubanLib.Pet:IsAlive()
			and not ZubanLib.Pet:IsFeeding())) then
		-- time for food!
		self.Button.SecureButton:SetAlpha(self.Button._normalAlpha);
		return true;
	else
		self.Button.SecureButton:SetAlpha(self.Button._petHappyAlpha);
		return false;
	end
end

function Petster.Feed:OnPetBarUpdate()
	local family = ZubanLib.Pet:CreatureFamily();
	local petHealth = ZubanLib.Pet:Health();
	
	--Petster:Debug("OnPetBarUpdate: "..tostring(family).." "..tostring(unit));
	
	if (ZubanLib.Pet:Exists() and family ~= nil and petHealth ~= nil and petHealth > 0) then
		if (ZubanLib.Player:AffectingCombat() or ZubanLib.Pet:AffectingCombat()) then
			-- put up the mend pet icon
			self.Button:SetButtonTexture(self.Button._mendPetTexture);
		elseif (PetsterPetFamilyState[family] ~= nil) then
			-- apply saved variables
			self.Button.SelectedFood = PetsterPetFamilyState[family].SelectedFood;
			self.Button:SetSelectedFood(family, self.Button.SelectedFood);
		else
			self.Button:SetSelectedFood(family, nil);
		end
	else
		-- update UI
		self.Button.SelectedFood = nil;
		self.Button:SetSelectedFoodUI(nil);
		
		-- put up the call pet icon
		self.Button:SetButtonTexture(self.Button._callPetTexture);
	end
end

function Petster.Feed:WriteSettings()
	Petster:Write("Pet Food Settings:");
	PetsterPetFamilyState:ForEachSelectedFood(
		function(family, food)
			ZubanLib.IO:Write(tostring(family)..": "..tostring(food.Link));
		end
	);
	Petster:Write("MacroText:");
	ZubanLib.IO:Write(self.Button:GetMacroText());
end

function Petster.Feed:WriteState()
	Petster:Write("PetsterPetFamilyState:");
	ZubanLib.IO:WriteTable(PetsterPetFamilyState);
end

function Petster.Feed:CastFeedPet(allowHappyCast)
	Petster:Warn("Not Implemented.");
end

function Petster.Feed:Reset()
	PetsterPetFamilyState = {};
	PetsterButtonState = {
		Enabled = true;
		Scale = Petster.MoverTemplate._normalScale;
		Locked = false;
	};
	
	self:OnVariablesLoaded();
	
	self.Button.SelectedFood = nil;
	self.Button:SetSelectedFoodUI(nil);
	self.Button:SetButtonTexture(nil);

	self.Frame:ClearAllPoints();
	self.Frame:SetPoint("CENTER", "UIParent", "CENTER", 0, 0);
	self.Frame:Show();
end

function Petster.Feed.Button:OnLoad()
	if (not ZubanLib.Unit:IsHunter() and not ZubanLib.Unit:IsWarlock()) then
		return;
	end
	
	this:RegisterEvent("BAG_UPDATE");
	this:RegisterForClicks("AnyUp");
end

function Petster.Feed.Button:SetMacroText(text)
	self.SecureButton:SetAttribute("macrotext", text);
end

function Petster.Feed.Button:OnDoubleClick(button)
	Petster:Debug("Button:OnDoubleClick");
	
	self.SecureButton:SetAttribute("macrotext", self:GetMacroText());
	self:OnFeedPet();
end

function Petster.Feed.Button:OnFeedPet()
	Petster:Write(PetsterResources.FeedingPet..": "..self.SelectedFood.Link);
end

function Petster.Feed.Button:OnPreClick(button, down)
	Petster:Debug("Button:OnPreClick");

	if (IsShiftKeyDown() and ZubanLib.Pet:Health() == 0) then
		-- check that the pet is dead before attempting to revive
		self.SecureButton:SetAttribute("macrotext", self._castTextShift);
	elseif (IsAltKeyDown()) then
		self.SecureButton:SetAttribute("macrotext", self._castTextAlt);
	else
		self.SecureButton:SetAttribute("macrotext", self._castText);
	end

	if (CursorHasItem()) then
		Petster.Feed.Button:OnReceiveDrag();
		self.SecureButton:SetAttribute("macrotext", ATTRIBUTE_NOOP);
	elseif (not IsModifierKeyDown() and self.SelectedFood ~= nil) then
		if (not ZubanLib.Container:FindBagSlotBySubName(self.SelectedFood.Name)) then
			-- could not find food in bags
			Petster:Write(PetsterResources.FoodNotFound);
		else
			-- TODO: still have to figure out how to recognize a double-click properly,
			-- as far as I can tell, double-clicking cannot be used as a modifier in the current
			-- WoW 2.0 UI API
			
			-- do not feed if pet is happy, override this with a double-click
			--if (Petster.Feed:OnPetHappiness()) then
				self.SecureButton:SetAttribute("macrotext", self:GetMacroText());
				self:OnFeedPet();
			--end
		end
	end

	Petster:Debug(self.SecureButton:GetAttribute("macrotext"));
end

function Petster.Feed.Button:OnReceiveDrag()
	if (not ZubanLib.Pet:Exists()) then
		Petster:Warn(PetsterResources.CallFirst);
		return;
	end
	
	if (ZubanLib.Pet:Exists()
		and CursorHasItem()
		and ZubanLib.Cursor ~= nil
		and ZubanLib.Cursor.Attributes ~= nil
		and ZubanLib.Cursor.Attributes.Location == "Container"
		and ZubanLib.Cursor.Attributes.Name ~= nil
		and ZubanLib.Cursor.Attributes.Texture ~= nil
		and ZubanLib.Cursor.Attributes.Bag ~= nil
		and ZubanLib.Cursor.Attributes.Slot ~= nil) then

		self.SelectedFood = {
			Name = ZubanLib.Cursor.Attributes.Name;
			Link = ZubanLib.Cursor.Attributes.Link;
			Texture = ZubanLib.Cursor.Attributes.Texture;
		};
		
		-- update the state and button
		self:SetSelectedFood(ZubanLib.Pet:CreatureFamily(), self.SelectedFood);
		ZubanLib.Cursor:Clear();
		ClearCursor();
		return true;
	end
	
	return false;
end

function Petster.Feed.Button:GetMacroText()
	--[[
	/cast [target=pet, dead] Revive Pet; [modifier:shift] Revive Pet; [nopet] Call Pet; [pet, combat] Mend Pet; [pet, nocombat] Feed Pet;		
	/use [pet:Cat, nocombat] Roasted Quail; [pet:Ravager, nocombat] Roasted Quail; [pet:Wind Serpent, nocombat] Homemade Cherry Pie;
	]]
	
	local castText = string.format("%s [pet, nocombat] %s;\n", self._castText, PetsterResources.Spells.FeedPet);
	local useText = "/use";

	PetsterPetFamilyState:ForEachSelectedFood(
		function(family, food)
			local format = " [pet:%s, nocombat] %s;";
			useText = useText..string.format(format, tostring(family), tostring(food.Name));
		end
	);
	
	return castText..useText;
end

function Petster.Feed.Button:SetSelectedFood(family, food)
	if (family == nil) then
		Petster:Warn("Error: pet family unspecified");
		return;
	end
	
	if (food ~= nil) then
		-- update saved variables
		if (PetsterPetFamilyState[family] == nil) then
			PetsterPetFamilyState[family] = {};
		end

		PetsterPetFamilyState[family].SelectedFood = food;

		-- update UI
		self.SelectedFood = food;
		self:SetSelectedFoodUI(food);
	else
		-- remove the food
		PetsterPetFamilyState:RemoveFood(family);
		
		-- update UI
		self.SelectedFood = nil;
		self:SetSelectedFoodUI(nil);
	end
end

function Petster.Feed.Button:SetButtonTexture(texture)
	SetItemButtonTexture(self.SecureButton, texture);
	self:UpdateButtonCount(nil);
	self.SecureButton:SetAlpha(self._normalAlpha);
	
	local warn = getglobal(self.SecureButton:GetName().."WarnCount");
	warn:SetText(nil);
	warn:Hide();
end

function Petster.Feed.Button:SetSelectedFoodUI(food)
	if (food ~= nil) then
		SetItemButtonTexture(self.SecureButton, food.Texture);
		self:UpdateButtonCount(food);
	else
		SetItemButtonTexture(self.SecureButton, nil);
		self:UpdateButtonCount(nil);
	end
end

function Petster.Feed.Button:OnBagUpdate()
	Petster:Debug("Button:OnBagUpdate");
	Petster.Feed:OnPetBarUpdate();
end

function Petster.Feed.Button:UpdateButtonCount(food)
	if (food ~= nil and food.Name ~= nil) then
		food.Count = ZubanLib.Container:CountByName(food.Name);
		SetItemButtonCount(self.SecureButton, food.Count);
		
		if (food.Count <= self._warnThreshold) then
			getglobal(self.SecureButton:GetName().."WarnCount"):SetText(food.Count);
			getglobal(self.SecureButton:GetName().."WarnCount"):Show();
		else
			getglobal(self.SecureButton:GetName().."WarnCount"):SetText(nil);
			getglobal(self.SecureButton:GetName().."WarnCount"):Hide();
		end
	else
		SetItemButtonCount(self.SecureButton, nil);
	end
end

function Petster.Feed.Button:OnEnter()
	-- display tooltip
	GameTooltip:SetOwner(this, "ANCHOR_RIGHT");
	
	local texture = getglobal(self.SecureButton:GetName().."IconTexture"):GetTexture();
	
	if (texture == self._callPetTexture) then
		GameTooltip:SetText(PetsterResources.Spells.CallPet);	
		GameTooltip:AddLine(PetsterResources.ForceRevivePet, "", 1, 1, 1);
	elseif (texture == self._mendPetTexture) then
		GameTooltip:SetText(PetsterResources.Spells.MendPet);	
	elseif (self.SelectedFood ~= nil and self.SelectedFood.Link ~= nil) then
		-- display the selected food
		--if (Petster.Feed:OnPetHappiness()) then
			GameTooltip:SetText(PetsterResources.Feed);
		--else
		--	GameTooltip:SetText(PetsterResources.ForceFeed);
		--end
		GameTooltip:AddLine(self.SelectedFood.Link, "", 1, 1, 1);
		GameTooltip:AddLine(PetsterResources.ForceDismissPet, "", 1, 1, 1);		
	else
		-- no food selected
		GameTooltip:SetText(PetsterResources.NoFood1);
		GameTooltip:AddLine(PetsterResources.NoFood2, "", 1, 1, 1);
	end
	
	GameTooltip:Show();
end

function Petster.Feed:GetEnabled()
	return PetsterButtonState.Enabled;
end

function Petster.Feed:SetEnabled(enabled)
	if (enabled) then
		self.Frame:Show();
	else
		self.Frame:Hide();
	end
	
	PetsterButtonState.Enabled = enabled;
end

function Petster.Feed:ToggleEnabled()
	if (not self:GetEnabled()) then
		self:SetEnabled(true);
	else
		self:SetEnabled(false);
	end
end

function Petster.Feed:OnCommand(command)
	local action, value = string.split(" +", string.lower(string.trim(command)));

	if (action ~= nil) then		
		if (action == "reset") then
			self:Reset();
			if (Petster.Ex ~= nil) then
				Petster.Ex:Reset();
			end
			Petster:Write("Settings reset.");
			return;
		elseif (action == "options") then
			if (Petster.Options ~= nil) then
				Petster.Options:ToggleOptions();
			end
			return;
		elseif (action == "lock") then
			self.Mover:ToggleLock();
			return;
		elseif (action == "size") then
			self.Mover:ToggleSize();
			return;
		elseif (action == "bar") then
			if (Petster.Options ~= nil) then
				Petster.Options.Ex.Enabled:Click();
			end
			return;
		elseif (action == "feed") then
			self:ToggleEnabled();
			return;
		elseif (action == "settings") then
			self:WriteSettings();
			return;
		elseif (action == "debug") then
			Petster._debug = not Petster._debug;
			return;
		end
	end
	
	ZubanLib.IO.Chat:Write(PetsterResources.Usage);
	ZubanLib.IO.Chat:Write(PetsterResources.UsageOptions);
	ZubanLib.IO.Chat:Write(PetsterResources.UsageLock);
	ZubanLib.IO.Chat:Write(PetsterResources.UsageSize);
	ZubanLib.IO.Chat:Write(PetsterResources.UsageReset);
	ZubanLib.IO.Chat:Write(PetsterResources.UsageFeed);
	ZubanLib.IO.Chat:Write(PetsterResources.UsageBar);
end

--
-- Feed Pet Button Mover object
--
Petster.Feed.Mover = Petster.MoverTemplate:New{};

function Petster.Feed.Mover:GetScale()
	return PetsterButtonState.Scale;
end

function Petster.Feed.Mover:SetScale(scale)
	if (scale == nil) then
		scale = self._normalScale;
	end
	self.SecureAnchor:SetScale(scale);
	PetsterButtonState.Scale = scale;
end

function Petster.Feed.Mover:GetLocked()
	return PetsterButtonState.Locked;
end

function Petster.Feed.Mover:SetLocked(locked)
	if (not locked) then
		self.SecureAnchor:SetAlpha(self._normalAlpha);
	else
		self.SecureAnchor:SetAlpha(self._lockedAlpha);
	end
	PetsterButtonState.Locked = locked;
	Petster.Feed:OnPetHappiness();
end
