--
-- ButtonCollection class
--
Petster.ButtonCollection = ZubanLib.Object:New{
	_normalAlpha = 1;
	Count = 0;
};

function Petster.ButtonCollection:Initialize(frameName)
	self.Frame = getglobal(frameName);
	self.Frame.Buttons = self;
end

function Petster.ButtonCollection:ForEach(action)
	for i = 1, self.Count do
		action(self[i], i);
	end
end

function Petster.ButtonCollection:SetLocked(locked)
	self:ForEach(
		function(button)
			button.SecureButton:EnableMouseWheel(not locked);
		end
	);
end

function Petster.ButtonCollection:EnableMouseWheel(enabled)
	self:ForEach(
		function(button)
			button.SecureButton:EnableMouseWheel(enabled);
		end
	);
end

function Petster.ButtonCollection:SetAlpha(alpha)
	self.Frame:SetAlpha(alpha);
end

function Petster.ButtonCollection:SetVisibility(visible)
	if (visible) then
		self.Frame:Show();
	else
		self.Frame:Hide();
	end
end

--
-- ExtendedButtonTemplate class
--
Petster.ExtendedButtonTemplate = ZubanLib.Object:New{
	_minSlot = 1;
	_maxSlot = 120;
	_minSelector = -5;
	_maxSelector = 5;
	_largeIncrement = 10;
	SecureButton = nil;
	Selector = nil;
	Pid = nil;
	Category = nil;
};

function Petster.ExtendedButtonTemplate:Initialize(buttonName, pid, category)
	self.SecureButton = getglobal(buttonName);
	self.SecureButton.Button = self;
	self.Pid = pid;
	self.Category = category;
	
	self.SecureButton:SetAttribute("type", "action");
	self.SecureButton:SetAttribute("action", 1);
	self.SecureButton:EnableMouseWheel(true);
	self.SecureButton:SetClampedToScreen(true);
	self.SecureButton:SetScript("OnAttributeChanged", ActionButton_Update);
	if ShiftFixClick_ActionButton then ShiftFixClick_ActionButton(self.SecureButton) end
	
	self.Selector = CreateFrame("Frame", buttonName.."_Selector", self.SecureButton, "PetsterExtendedSelectorTemplate");
	self.Selector:Hide();
	self.Selector:ClearAllPoints();
	self.Selector:SetPoint("LEFT", self.SecureButton, "RIGHT", 0, 0);
end

function Petster.ExtendedButtonTemplate:SetSlot(slot)
	slot = tonumber(slot);
	
	if (slot ~= nil and slot >= self._minSlot and slot <= self._maxSlot) then
		--Petster:Debug("slot="..tostring(slot));
		self.SecureButton:SetAttribute("type", "action");
		self.SecureButton:SetAttribute("action", slot);
		self:UpdateSelector();
		if (PetsterExtendedState[self.SecureButton:GetName()] == nil) then
			PetsterExtendedState[self.SecureButton:GetName()] = {};
		end
		PetsterExtendedState[self.SecureButton:GetName()].Slot = slot;		
	end
end

function Petster.ExtendedButtonTemplate:OnMouseWheel(direction)
	local slot = self.SecureButton:GetAttribute("action");

	local increment = 1;
	
	if (IsShiftKeyDown()) then
		increment = self._largeIncrement;
	end

	if (direction == 1) then
		slot = slot + increment;
		
		if (slot > self._maxSlot) then
			slot = self._minSlot;
		end
		
		while (not HasAction(slot)) do
			slot = slot + 1;
			if (slot > self._maxSlot) then
				slot = self._minSlot;
			end
		end
	elseif (direction == -1) then
		slot = slot - increment;
		
		if (slot < self._minSlot) then
			slot = self._maxSlot;
		end
		
		while (not HasAction(slot)) do
			slot = slot - 1;
			if (slot < self._minSlot) then
				slot = self._maxSlot;
			end
		end
	end	
	
	if (HasAction(slot) and slot >= self._minSlot and slot <= self._maxSlot) then
		Petster:Debug("slot="..tostring(slot));
		self.SecureButton:SetAttribute("type", "action");
		self.SecureButton:SetAttribute("action", slot);
		self:UpdateSelector();
		if (PetsterExtendedState[self.SecureButton:GetName()] == nil) then
			PetsterExtendedState[self.SecureButton:GetName()] = {};
		end
		PetsterExtendedState[self.SecureButton:GetName()].Slot = slot;
		
		Petster.Options.Ex.WheelEditEnabled:SetText(self, slot);
	end
end

function Petster.ExtendedButtonTemplate:OnEnter()
	if (PetsterExtendedState.WheelEditEnabled) then
		self.Selector:Show();
		self:UpdateSelector();
	end
	ActionButton_SetTooltip();
end

function Petster.ExtendedButtonTemplate:OnLeave()
	self.Selector:Hide();
	self.SecureButton.updateTooltip = nil;
	GameTooltip:Hide();
end

function Petster.ExtendedButtonTemplate:UpdateSelector()
	local slot = self.SecureButton:GetAttribute("action");
	
	for i = self._minSelector, self._maxSelector do
		local current = slot + i;
		
		if (current > self._maxSlot) then
			current = current - self._maxSlot;
		elseif (current < self._minSlot) then
			current = current + self._maxSlot;
		end

		local slotButton = getglobal(self.SecureButton:GetName().."_SelectorSlotButton"..tostring(i));
		local texture = GetActionTexture(current);
		SetItemButtonTexture(slotButton, texture);
	end
end

function Petster.ExtendedButtonTemplate:SetVisibility(visible)
	-- had to wrapper the CheckButton inside a parent Frame since Blizzard's
	-- code was turning the buttons back on even after hiding them during
	-- PLAYER_ENTERING_WORLD
	local frame = self.SecureButton:GetParent();
	
	if (visible) then
		--self.SecureButton:Show();
		frame:Show();
	else
		--self.SecureButton:Hide();
		frame:Hide();
	end
	
	if (PetsterExtendedState[self.SecureButton:GetName()] == nil) then
		PetsterExtendedState[self.SecureButton:GetName()] = {};
	end
	PetsterExtendedState[self.SecureButton:GetName()].Visible = visible;
end

--
-- Petster Extended object
--
Petster.Ex = ZubanLib.Object:New{
	Frame = nil;
};

--
-- Petster Extended ButtonCollection class
--
Petster.Ex.ButtonCollection = Petster.ButtonCollection:New{
	Frame = nil;
};

function Petster.Ex.ButtonCollection:Initialize(frameName)
	self.Frame = getglobal(frameName);
	self.Frame.Buttons = self;
end

function Petster.Ex.ButtonCollection:SetLocked(locked)
	self:SetAlpha(self._normalAlpha);
end

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

function Petster.Ex:SetSpacing(spacing)
	local previous = nil;
	
	self.PresentButtons:ForEach(
		function(button, i)
			if (i > 1) then
				button.SecureButton:ClearAllPoints();
				button.SecureButton:SetPoint("TOPLEFT", previous.SecureButton, "TOPRIGHT", spacing, 0);
			end
			previous = button;
		end
	);
	
	self.AwayButtons:ForEach(
		function(button, i)
			if (i > 1) then
				button.SecureButton:ClearAllPoints();
				button.SecureButton:SetPoint("TOPLEFT", previous.SecureButton, "TOPRIGHT", spacing, 0);
			end
			previous = button;
		end
	);
	
	PetsterExtendedState.SpacingSliderValue = spacing;
end

function Petster.Ex:OnLoad()
	self.Frame = getglobal("PetsterExtendedFrame");
	
	if (not ZubanLib.Unit:IsHunter() and not ZubanLib.Unit:IsWarlock()) then
		self.Frame:Hide();
		return;
	end
	
	this:RegisterEvent("PET_BAR_UPDATE");
	this:RegisterEvent("PLAYER_REGEN_ENABLED");
	this:RegisterEvent("PLAYER_REGEN_DISABLED");
	this:RegisterEvent("UNIT_HAPPINESS");

	-- SavedVariablesPerCharacter
	PetsterExtendedState = {
		Enabled = true;
		Scale = Petster.MoverTemplate._normalScale;
		Locked = false;
		WheelEditEnabled = true;
		SpacingSliderValue = 0;
	};

	if (ZubanLib.Unit:IsWarlock()) then
		PetsterExtendedState.Enabled = false;
	end

	self.Mover:Initialize("PetsterExtendedMoverAnchor", "PetsterExtendedFrame");

	self.PresentButtons:Initialize("PetsterExtendedPresentGroup");
	
	self.PresentButtons:ForEach(
		function(button, i)
			button:Initialize(self.PresentButtons.Frame:GetName().."Button"..tostring(i), i, "Present");
			--self.Mover.SecureAnchor:SetAttribute("anchorchild", button.SecureButton);
		end
	);
	
	self.AwayButtons:Initialize("PetsterExtendedAwayGroup");

	self.AwayButtons:ForEach(
		function(button, i)
			button:Initialize(self.AwayButtons.Frame:GetName().."Button"..tostring(i), i, "Away");
			--self.Mover.SecureAnchor:SetAttribute("anchorchild", button.SecureButton);
		end
	);

	this:SetScript("OnEvent", 
		function()
			if (event == "PET_BAR_UPDATE") then
				Petster:Debug("PET_BAR_UPDATE");
				self:OnPetBarUpdate();
			elseif (event == "PLAYER_REGEN_ENABLED") then
				Petster:Debug("PLAYER_REGEN_ENABLED");
				self:OnPetBarUpdate();
			elseif (event == "PLAYER_REGEN_DISABLED") then
				Petster:Debug("PLAYER_REGEN_DISABLED");
				self:OnPetBarUpdate();
			elseif (event == "UNIT_HAPPINESS" and arg1 == "pet") then
				Petster:Debug("UNIT_HAPPINESS");
				self:OnPetBarUpdate();
			end
		end
	);
end

function Petster.Ex:OnVariablesLoaded()
	self:SetEnabled(PetsterExtendedState.Enabled);
	Petster.Options.Ex.Enabled:SetChecked(PetsterExtendedState.Enabled);
	
	self.Mover:SetLocked(PetsterExtendedState.Locked);
	Petster.Options.Ex.Locked:SetChecked(PetsterExtendedState.Locked);
	
	self.Mover:SetScale(PetsterExtendedState.Scale);	
	Petster.Options.Ex.Size:SetChecked(PetsterExtendedState.Scale == self.Mover._smallScale);

	self:SetSpacing(PetsterExtendedState.SpacingSliderValue);
	Petster.Options.Ex.SpacingSlider:SetValue(PetsterExtendedState.SpacingSliderValue);
	
	self:SetWheelEdit(PetsterExtendedState.WheelEditEnabled);
	Petster.Options.Ex.WheelEditEnabled:SetChecked(PetsterExtendedState.WheelEditEnabled);
	
	self.PresentButtons:ForEach(
		function(button)
			local slot = 1;
			if (PetsterExtendedState[button.SecureButton:GetName()] ~= nil
					and PetsterExtendedState[button.SecureButton:GetName()].Slot ~= nil) then
				slot = PetsterExtendedState[button.SecureButton:GetName()].Slot;
			end
			button.SecureButton:SetAttribute("action", slot);
			Petster.Options.Ex.WheelEditEnabled:SetText(button, slot);
			
			local visible = true;
			if (PetsterExtendedState[button.SecureButton:GetName()] ~= nil
					and PetsterExtendedState[button.SecureButton:GetName()].Visible ~= nil) then
				visible = PetsterExtendedState[button.SecureButton:GetName()].Visible;
			end
			button:SetVisibility(visible);
			Petster:Debug(button.SecureButton:IsShown());
			Petster.Options.Ex.Present.Enabled:SetChecked(button, visible);
		end
	);
	
	self.AwayButtons:ForEach(
		function(button)
			local slot = 1;
			if (PetsterExtendedState[button.SecureButton:GetName()] ~= nil
					and PetsterExtendedState[button.SecureButton:GetName()].Slot ~= nil) then
				slot = PetsterExtendedState[button.SecureButton:GetName()].Slot;
			end
			button.SecureButton:SetAttribute("action", slot);
			Petster.Options.Ex.WheelEditEnabled:SetText(button, slot);
			
			local visible = true;
			if (PetsterExtendedState[button.SecureButton:GetName()] ~= nil
					and PetsterExtendedState[button.SecureButton:GetName()].Visible ~= nil) then
				visible = PetsterExtendedState[button.SecureButton:GetName()].Visible;
			end
			button:SetVisibility(visible);
			Petster:Debug(button.SecureButton:IsShown());
			Petster.Options.Ex.Away.Enabled:SetChecked(button, visible);
		end
	);
end

function Petster.Ex:OnPetBarUpdate()
	if (ZubanLib.Pet:Exists() and ZubanLib.Pet:Health() > 0) then
		self.PresentButtons:SetVisibility(true);
		self.AwayButtons:SetVisibility(false);
	else
		self.PresentButtons:SetVisibility(false);
		self.AwayButtons:SetVisibility(true);
	end
end

function Petster.Ex:Reset()
	PetsterExtendedState = {
		Enabled = true;
		Scale = Petster.MoverTemplate._normalScale;
		Locked = false;
		WheelEditEnabled = true;
		SpacingSliderValue = 0;
	};
	
	self.Frame:ClearAllPoints();
	self.Frame:SetPoint("CENTER", "UIParent", "CENTER", 0, 0);
	self.Frame:Show();
end

function Petster.Ex:SetWheelEdit(enabled)
	self.PresentButtons:EnableMouseWheel(enabled);
	self.AwayButtons:EnableMouseWheel(enabled);
	PetsterExtendedState.WheelEditEnabled = enabled;
end

--
-- Petster Extended Mover object
--
Petster.Ex.Mover = Petster.MoverTemplate:New{
	_smallScale = 0.8;
	_smallSize = 14;
};

function Petster.Ex.Mover:GetScale()
	return PetsterExtendedState.Scale;
end

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

function Petster.Ex.Mover:GetLocked()
	return PetsterExtendedState.Locked;
end

function Petster.Ex.Mover:SetLocked(locked)
	if (not locked) then
		self.SecureAnchor:SetAlpha(self._normalAlpha);
	else
		self.SecureAnchor:SetAlpha(self._lockedAlpha);
	end
	PetsterExtendedState.Locked = locked;
	
	Petster.Ex.PresentButtons:SetLocked(locked);
	Petster.Ex.AwayButtons:SetLocked(locked);
end

function Petster.Ex.Mover:ToggleLock()
	Petster.Options.Ex.Locked:Click();
end

function Petster.Ex.Mover:GetRightClickTooltip()
	return PetsterResources.Options.RightClick;
end

function Petster.Ex.Mover:OnRightClick()
	Petster.Options:ToggleOptions();
end

--
-- Petster Extended ButtonCollection
--
Petster.Ex.PresentButtons = Petster.Ex.ButtonCollection:New{
	Count = 6;
	[1] = Petster.ExtendedButtonTemplate:New{};
	[2] = Petster.ExtendedButtonTemplate:New{};
	[3] = Petster.ExtendedButtonTemplate:New{};
	[4] = Petster.ExtendedButtonTemplate:New{};
	[5] = Petster.ExtendedButtonTemplate:New{};
	[6] = Petster.ExtendedButtonTemplate:New{};
};

Petster.Ex.AwayButtons = Petster.Ex.ButtonCollection:New{
	Count = 6;
	[1] = Petster.ExtendedButtonTemplate:New{};
	[2] = Petster.ExtendedButtonTemplate:New{};
	[3] = Petster.ExtendedButtonTemplate:New{};
	[4] = Petster.ExtendedButtonTemplate:New{};
	[5] = Petster.ExtendedButtonTemplate:New{};
	[6] = Petster.ExtendedButtonTemplate:New{};
};
