--[[
	PopBar 2.3

	Original version by Mugendai

	WoW 2.0 Fixed by Arbi

	This mod is a highly configurable auto hiding
	action bar.  You can move it around, set its
	size and all kinds of junk.
   ]]

POPBAR_MAX_ID=72;
POPBAR_MAX_HIGH_ID=120;
POPBAR_HIGH_ID=109;
POPBAR_UPDATETIME=0.1;
POPBAR_MAX_BARS=7;
POPBAR_MAX_ROWS=12;
POPBAR_MAX_COLS=12;
POPBAR_MAX_POPTIME=2;
PopBar_Config = { };
PopBar_Config.Enabled=1;
PopBar_Config.HideEmpty=0;
PopBar_Config.Rows=2;
PopBar_Config.Cols=12;
PopBar_Config.VAnchor=0;
PopBar_Config.HAnchor=0;
PopBar_Config.IDUp=0;
PopBar_Config.StartPage=5;
PopBar_Config.StartButton=12;
PopBar_Config.RowShow=1;
PopBar_Config.ColShow=12;
PopBar_Config.Orient=0;
PopBar_Config.InArea=0;
PopBar_Config.TurnPages=0;
PopBar_Config.CooldownText=1;
PopBar_Config.KnobAlpha=1;
PopBar_Config.BarAlpha=1;
PopBar_Config.HideKeys=0;
PopBar_Config.HideKeyMod=0;
PopBar_Config.FlipH=0;
PopBar_Config.FlipV=0;
PopBar_Config.PopTime=0;
PopBar_Config.Scale=1.0;
--Store this config for safe load
MCom.safeLoad("PopBar_Config");

PopBar_StartID=60;
PopBar_Initialized=0;
PopBar_Hovering=false;
PopBar_Toggled=false;
PopBar_LastUpdate=0;
PopBar_AnchorUpdated=false;
PopBar_RowLimit=6;
PopBar_ColLimit=12;

local PopBar_Loaded=false;
local PopBar_Combat=false;
local PopBar_ConvertDone = false;

function PopBar_OnUpdate(elapsed)
	if (PopBar_Config.Enabled == 1) then
		PopBar_LastUpdate = PopBar_LastUpdate + elapsed;
		if (PopBar_LastUpdate >= POPBAR_UPDATETIME) then 
			PopBar_LastUpdate = 0;

			if (not PopBar_AnchorUpdated) then
				PopBar_AnchorUpdated = true;
				local PopBar_VAnchor = "BOTTOM";
				local PopBar_HAnchor = "LEFT";
				if (PopBar_Config.VAnchor == 1) then
					PopBar_VAnchor = "TOP";
				end
				if (PopBar_Config.HAnchor == 1) then
					PopBar_HAnchor = "RIGHT";
				end
				this:ClearAllPoints();
				this:SetPoint(PopBar_VAnchor..PopBar_HAnchor,"PopBarKnob","CENTER",0,0);
			end

			local xPos, yPos = GetCursorPosition();
			local left = PopBar:GetLeft() * PopBar:GetEffectiveScale();
			local right = PopBar:GetRight() * PopBar:GetEffectiveScale();
			local top = PopBar:GetTop() * this:GetEffectiveScale();
			local bottom = PopBar:GetBottom() * PopBar:GetEffectiveScale();
			local knob = getglobal("PopBarKnob");
			local kleft = nil;
			local kright = nil;
			local ktop = nil;
			local kbottom = nil;
			if (knob) then
				kleft = knob:GetLeft() * UIParent:GetEffectiveScale();
				kright = knob:GetRight() * UIParent:GetEffectiveScale();
				ktop = knob:GetTop() * UIParent:GetEffectiveScale();
				kbottom = knob:GetBottom() * UIParent:GetEffectiveScale();
				
				if (PopBar_Config.KnobAlpha > 0) then
					if (not knob:IsVisible()) then
						knob:Show();
					end
				else
					if (knob:IsVisible()) then
						knob:Hide();
					end
				end
					
				if (this:GetAlpha() ~= PopBar_Config.BarAlpha) then
					this:SetAlpha(PopBar_Config.BarAlpha);
				end
				
				if (knob:GetAlpha() ~= PopBar_Config.KnobAlpha) then
					knob:SetAlpha(PopBar_Config.KnobAlpha);
				end
			end
			
			-- resize the PopBar Frame to minimize it's overlaying something.
			local width = PopBar_Config.Cols *(36 + 6) * this:GetEffectiveScale();
			local height = PopBar_Config.Rows *(36 + 6) * this:GetEffectiveScale();
			if(this:GetWidth() ~= width) then 
				this:SetWidth(width);
			end
			if (this:GetHeight() ~= height) then 
				this:SetHeight(height);
			end
			
			if (xPos and yPos and left and right and top and bottom and knob and kleft and kright and ktop and kbottom) then
				local butsize = (36 * this:GetEffectiveScale());
				local spacesize = (6 * this:GetEffectiveScale());
				if ((PopBar_Config.InArea == 1) or PopBar_Hovering) then
					if (PopBar_Config.HAnchor==1) then
						left = right - ((PopBar_Config.Cols * butsize) + ((PopBar_Config.Cols - 1) * spacesize));
					else
						right = left + ((PopBar_Config.Cols * butsize) + ((PopBar_Config.Cols - 1) * spacesize));
					end
					if (PopBar_Config.VAnchor==1) then
						bottom = top - ((PopBar_Config.Rows * butsize) + ((PopBar_Config.Rows - 1) * spacesize));
					else
						top = bottom + ((PopBar_Config.Rows * butsize) + ((PopBar_Config.Rows - 1) * spacesize));
					end
				elseif ((PopBar_Config.ColShow > 0) and (PopBar_Config.RowShow > 0)) then
					if (PopBar_Config.HAnchor==1) then
						left = right - ((PopBar_Config.ColShow * butsize) + ((PopBar_Config.ColShow - 1) * spacesize));
					else
						right = left + ((PopBar_Config.ColShow * butsize) + ((PopBar_Config.ColShow - 1) * spacesize));
					end
					if (PopBar_Config.VAnchor==1) then
						bottom = top - ((PopBar_Config.RowShow * butsize) + ((PopBar_Config.RowShow - 1) * spacesize));
					else
						top = bottom + ((PopBar_Config.RowShow * butsize) + ((PopBar_Config.RowShow - 1) * spacesize));
					end
				else
					left = -1;
					right = -1;
					top = -1;
					bottom = -1;
				end
				
				if (((xPos >= left) and (xPos <= right) and (yPos >= bottom) and (yPos <= top)) or ((xPos >= kleft) and (xPos <= kright) and (yPos >= kbottom) and (yPos <= ktop))) then
					PopBar_Hover(1);
				else
					PopBar_Hover(0);
				end
			end
		end
	end
end

function PopBar_SetRows(checked, count)
	if (count) then
		if (count > POPBAR_MAX_ROWS) then
			count = POPBAR_MAX_ROWS;
		end
		if (count < 1) then
			count = 1;
		end
		if (PopBar_Config.Rows ~= count) then
			PopBar_Config.Rows = count;
			PopBar_ColLimit = floor((POPBAR_MAX_ID + 12) / PopBar_Config.Rows);
			if (PopBar_ColLimit > POPBAR_MAX_COLS) then
				PopBar_ColLimit = POPBAR_MAX_COLS;
			end
			
			if (PopBar_Loaded) then
				if (PopBar_Config.Cols > PopBar_ColLimit) then
					PopBar_SetCols(0,PopBar_ColLimit);
				end
				if (PopBar_Config.ColShow > PopBar_ColLimit) then
					PopBar_SetColShow(0,PopBar_ColLimit);
				end
			end
		end
		PopBar_Initialize();
	end
end

function PopBar_SetCols(checked, count)
	if (count) then
		if (count > POPBAR_MAX_COLS) then
			count = POPBAR_MAX_COLS;
		end
		if (count < 1) then
			count = 1;
		end
		if (PopBar_Config.Cols ~= count) then
			PopBar_Config.Cols = count;
			PopBar_RowLimit = floor((POPBAR_MAX_ID + 12) / PopBar_Config.Cols);
			if (PopBar_RowLimit > POPBAR_MAX_ROWS) then
				PopBar_RowLimit = POPBAR_MAX_ROWS;
			end
			if (PopBar_Loaded) then
				if (PopBar_Config.Rows > PopBar_RowLimit) then
					PopBar_SetRows(0,PopBar_RowLimit);
				end
				if (PopBar_Config.RowShow > PopBar_RowLimit) then
					PopBar_SetRowShow(0,PopBar_RowLimit);
				end
			end
		end
		PopBar_Initialize();
	end
end

function PopBar_SetRowShow(checked, count)
	if (count) then
		local newCount = count;
		if (newCount > PopBar_Config.Rows) then
			newCount = PopBar_Config.Rows;
		end
		if (newCount < 0) then
			newCount = 0;
		end
		if (PopBar_Config.RowShow ~= newCount) then
			PopBar_Config.RowShow = newCount;
		end
		PopBar_Update();
	end
end

function PopBar_SetColShow(checked, count)
	if (count) then
		local newCount = count;
		if (newCount > PopBar_Config.Cols) then
			newCount = PopBar_Config.Cols;
		end
		if (newCount < 0) then
			newCount = 0;
		end
		if (PopBar_Config.ColShow ~= newCount) then
			PopBar_Config.ColShow = newCount;
		end
		PopBar_Update();
	end
end

function PopBar_Toggle(toggle)
	if (toggle == 1) then
		if (not PopBar_Toggled) then
			PopBar_Toggled = true;
			PopBar_Update();
		end
	elseif (toggle == 0) then
		if (PopBar_Toggled) then
			PopBar_Toggled = false;
			PopBar_Update();
		end
	elseif (PopBar_Toggled) then
		PopBar_Toggled = false;
		PopBar_Update();
	else
		PopBar_Toggled = true;
		PopBar_Update();
	end
end

function PopBar_Hover(toggle)
	if (toggle == 1) then
		local canHover = false;
		if (Chronos) then
			if (Chronos.getTimer("POPBAR") == 0) then
				Chronos.startTimer("POPBAR");
			end
			if (not PopBar_Config.PopTime) then
				PopBar_Config.PopTime = 0;
			end
			if (Chronos.getTimer("POPBAR") >= PopBar_Config.PopTime) then
				canHover = true;
			end
		else
			canHover = true;
		end
		
		if ((not PopBar_Hovering) and canHover) then
			PopBar_Hovering = true;
			PopBar_Update();
		end
	else
		if (Chronos) then
			Chronos.endTimer("POPBAR");
		end
		if (PopBar_Hovering) then
			PopBar_Hovering = false;
			PopBar_Update();
		end
	end
end

function PopBar_Update(fullupdate)
	if (PopBar_Initialized == 1) then
		PopBar_StartID = ((PopBar_Config.StartPage - 1) * 12) + PopBar_Config.StartButton;
		for row=1, POPBAR_MAX_ROWS do
			for i=1, POPBAR_MAX_COLS do
				local button = getglobal(string.format ("PopBarButton%d%02d", row, i));
				if (button) then
					if (not fullupdate) then
						PopBarButton_CheckShow(button);
					else
						PopBarButton_Update(button);
					end
				end
			end
		end
		--Use MCom's save function to save the config
		MCom.saveConfig( {
			configVar = "PopBar_Config";
		});
	end
end

function PopBar_Initialize()
	PopBar:SetScale(PopBar_Config.Scale);
	PopBar_StartID = ((PopBar_Config.StartPage - 1) * 12) + PopBar_Config.StartButton;
	if (PopBar_Config.TurnPages==1) then
		PopBar_StartID = PopBar_StartID + ( ( GetActionBarPage() - 1 ) * 12 );
	end
	for row=1, POPBAR_MAX_ROWS do
		for i=1, POPBAR_MAX_COLS do
			local actualrow = 12 * ( row - 1 );
			local id;
			if (PopBar_Config.IDUp == 1) then
				id = PopBar_StartID + actualrow + ( i - 1 );
			elseif (PopBar_Config.FlipH==1) then
				id = PopBar_StartID - actualrow - 11 + ( i - 1 );
			else
				id = PopBar_StartID - actualrow - ( i - 1 );
			end
			local button = getglobal(string.format ("PopBarButton%d%02d", row, i));
			if ( row <= PopBar_Config.Rows ) and ( i <= PopBar_Config.Cols ) then
				local icon = getglobal(button:GetName().."Icon");
				local texture = GetActionTexture(id);
				if(not HasAction(id) and PopBar_Config.HideEmpty) then
					button.showgrid = 0;
				else
					button.showgrid = 1;
				end
				button:SetAttribute("type", "action");
				button:SetAttribute("action", id);
				button:SetAttribute("checkselfcast", true);
				button:SetAttribute("useparent-unit", true);
				button:SetAttribute("useparent-statebutton", true);
				icon:SetTexture(texture);
				PopBarButton_Update(button);
			else
				button.showgrid = 0;
				button:SetScript("OnAttributeChanged", PopBarButton_Update);
				button:SetAttribute("type", "action");
			end
			local cooldownText = getglobal(button:GetName().."CooldownCount");
			local cooldownframe = getglobal(button:GetName().."Cooldown");
			cooldownframe:SetFrameLevel(2);
			cooldownText:Show();
		end
	end
end

function PopBar_ResetPos()
	local knob = getglobal("PopBarKnob");
	knob:ClearAllPoints();
	knob:SetPoint("CENTER","UIParent","BOTTOM",10,65);
end

function PopBarButton_CheckShow(button)
	if (button) then
		local doShow = false;
		local row, col;
		if (string.len(button:GetID()) > 3) then
			_, _, row, col = string.find (button:GetID(), "(%d%d)(%d%d)");
		else
			_, _, row, col = string.find (button:GetID(), "(%d)(%d%d)");
		end
		local buttonCooldown = getglobal(button:GetName().."Cooldown");
		if (row and col) then
			row = tonumber(row);
			col = tonumber(col);
			if (PopBar_Config.VAnchor==1) then
				row = POPBAR_MAX_ROWS - (row - 1);
			end
			if (PopBar_Config.HAnchor==1) then
				col = POPBAR_MAX_COLS - (col - 1);
			end
			if ((row <= PopBar_Config.Rows) and (col <= PopBar_Config.Cols)) then
				if (((row <= PopBar_Config.RowShow) and (col <= PopBar_Config.ColShow)) or PopBar_Toggled or PopBar_Hovering) then
					doShow = true;
				end
			end
			if ((PopBar_Config.HideEmpty == 1) and ((HasAction(PopBarButton_GetPagedID(button)) == nil) and (button.showgrid == 0))) then
				doShow = false;
			end
		end	

	
		if (doShow) then
			if(not InCombatLockdown()) then 
				button:Show(); 
			end 
			if((row > PopBar_Config.RowShow) or (col > PopBar_Config.ColShow)) then
				buttonCooldown:Show();
			end 
			button:SetAlpha(1); 
		else
			if(not InCombatLockdown()) then 
				button:Hide(); 
			end 
			if(PopBar_Combat and (row <= PopBar_Config.Rows) and (col <= PopBar_Config.Cols)) then 
				button:Show(); 
			end
			button:SetAlpha(0); 
			buttonCooldown:Hide();
		end
	end
end

function PopBarButton_OnLoad()
	this.showgrid = 0;
	this.flashing = 0;
	this.flashtime = 0;
	PopBarButton_Update();
	this:RegisterForDrag("LeftButton", "RightButton");
	this:RegisterForClicks("LeftButtonUp", "RightButtonUp");
	this:RegisterEvent("PLAYER_ENTERING_WORLD");
	this:RegisterEvent("ACTIONBAR_SHOWGRID");
	this:RegisterEvent("ACTIONBAR_HIDEGRID");
	this:RegisterEvent("ACTIONBAR_SLOT_CHANGED");
	this:RegisterEvent("ACTIONBAR_PAGE_CHANGED");
	this:RegisterEvent("UPDATE_BINDINGS");
	this:RegisterEvent("PLAYER_REGEN_DISABLED"); 
	this:RegisterEvent("PLAYER_REGEN_ENABLED");
	this:SetScale(PopBar_Config.Scale);
	PopBarButton_UpdateHotkeys();
end

function PopBarButton_UpdateHotkeys(actionButtonType,button)
	if ( not actionButtonType ) then
		actionButtonType = "POPBARBUTTON";
	end
	if (not button) then
		button = this;
	end
	local hotkey = getglobal(button:GetName().."HotKey");	
	local buttonnumber, _ = string.gsub(button:GetName(), "PopBarButton(%d+)", "%1");
	local action = GetBindingKey(actionButtonType..buttonnumber);
	local buttonid = PopBarButton_GetPagedID(button);

	if (hotkey) then
		if (PopBar_Config.HideKeys==1) then
			hotkey:SetText("");
		else
			if (action) then
				local keyText = GetBindingText(action, "KEY_", 1);
				if (PopBar_Config.HideKeyMod==1) then
					while ( ( keyText ) and ( strlen(keyText) > 1 ) and (string.find(keyText, "-")) and (keyText ~= "KP -") and (keyText ~= "Num Pad -")) do
						firsti, lasti, keyText = string.find (keyText, "-(.+)");
					end
				end
				if ( ( not keyText ) or ( strlen(keyText) <= 0 ) ) then keyText = ""; end
				hotkey:SetText(keyText);
			else
				if ( not HasAction(buttonid) ) then
					hotkey:SetText("");
				elseif ( ActionHasRange(buttonid) ) then
					if ( IsActionInRange(buttonid) ) then
						hotkey:SetText(RANGE_INDICATOR);
						hotkey:SetTextHeight(8);
						hotkey:SetPoint("TOPRIGHT", this:GetName(), "TOPRIGHT", -3, 5);
					else
						hotkey:SetText("");			
					end
				end

			end
		end
	end
end

function PopBarButton_Update(button)
	if (not button) then
		button = this;
	end
	
	-- Determine whether or not the button should be flashing or not since the button may have missed the enter combat event
	local pagedID = PopBarButton_GetPagedID(button);
	if (pagedID ~= nil) then
		-- Special case code for bonus bar buttons
		-- Prevents the button from updating if the bonusbar is still in an animation transition
	
		if ( button.isBonus and button.inTransition ) then
			PopBarButton_UpdateUsable(button);
			PopBarButton_UpdateCooldown(button);
			return;
		end
		
		local icon = getglobal(button:GetName().."Icon");
		local buttonCooldown = getglobal(button:GetName().."Cooldown");
		local texture = GetActionTexture(pagedID);
		if ( texture ) then
			icon:SetTexture(texture);
			icon:Show();
			button.rangeTimer = TOOLTIP_UPDATE_TIME;
			button:SetNormalTexture("Interface\\Buttons\\UI-Quickslot2");
			-- Save texture if the button is a bonus button, will be needed later
			if ( button.isBonus ) then
				button.texture = texture;
			end
		else
			icon:Hide();
			buttonCooldown:Hide();
			button.rangeTimer = nil;
			button:SetNormalTexture("Interface\\Buttons\\UI-Quickslot");
		end
		PopBarButton_UpdateCount(button);
		if ( HasAction(pagedID) ) then
			this:RegisterEvent("ACTIONBAR_UPDATE_STATE");
			this:RegisterEvent("ACTIONBAR_UPDATE_USABLE");
			this:RegisterEvent("ACTIONBAR_UPDATE_COOLDOWN");
			this:RegisterEvent("UPDATE_INVENTORY_ALERTS");
			this:RegisterEvent("PLAYER_AURAS_CHANGED");
			this:RegisterEvent("PLAYER_TARGET_CHANGED");
			this:RegisterEvent("UNIT_INVENTORY_CHANGED");
			this:RegisterEvent("CRAFT_SHOW");
			this:RegisterEvent("CRAFT_CLOSE");
			this:RegisterEvent("TRADE_SKILL_SHOW");
			this:RegisterEvent("TRADE_SKILL_CLOSE");
			this:RegisterEvent("PLAYER_ENTER_COMBAT");
			this:RegisterEvent("PLAYER_LEAVE_COMBAT");
			this:RegisterEvent("START_AUTOREPEAT_SPELL");
			this:RegisterEvent("STOP_AUTOREPEAT_SPELL");

			button:Show();
			PopBarButton_UpdateState();
			PopBarButton_UpdateUsable();
			PopBarButton_UpdateCount(button);
			PopBarButton_UpdateCooldown(button);
			PopBarButton_UpdateFlash(button);
		elseif ( (PopBar_Config.HideEmpty == 1) and (button.showgrid == 0) ) then
			button:Hide();
		else
			this:UnregisterEvent("ACTIONBAR_UPDATE_STATE");
			this:UnregisterEvent("ACTIONBAR_UPDATE_USABLE");
			this:UnregisterEvent("ACTIONBAR_UPDATE_COOLDOWN");
			this:UnregisterEvent("UPDATE_INVENTORY_ALERTS");
			this:UnregisterEvent("PLAYER_AURAS_CHANGED");
			this:UnregisterEvent("PLAYER_TARGET_CHANGED");
			this:UnregisterEvent("UNIT_INVENTORY_CHANGED");
			this:UnregisterEvent("CRAFT_SHOW");
			this:UnregisterEvent("CRAFT_CLOSE");
			this:UnregisterEvent("TRADE_SKILL_SHOW");
			this:UnregisterEvent("TRADE_SKILL_CLOSE");
			this:UnregisterEvent("PLAYER_ENTER_COMBAT");
			this:UnregisterEvent("PLAYER_LEAVE_COMBAT");
			this:UnregisterEvent("START_AUTOREPEAT_SPELL");
			this:UnregisterEvent("STOP_AUTOREPEAT_SPELL");

			getglobal(button:GetName().."CooldownCount"):SetText("");
			getglobal(button:GetName().."Cooldown"):Hide();
		end

		-- Add a green border if button is an equipped item
		local border = getglobal(button:GetName().."Border");
		if ( IsEquippedAction(pagedID) ) then
			border:SetVertexColor(0, 1.0, 0, 0.35);
			border:Show();
		else
			border:Hide();
		end
		
		if ( GameTooltip:IsOwned(button) ) then
			PopBarButton_SetTooltip(button);
		else
			button.updateTooltip = nil;
		end

		PopBarButton_UpdateHotkeys("POPBARBUTTON",button);
		PopBarButton_CheckShow(button);
	
		-- Update Macro Text
		local macroName = getglobal(button:GetName().."Name");
		if ( not IsConsumableAction(pagedID) and not IsStackableAction(pagedID) ) then
			macroName:SetText(GetActionText(pagedID));
		else
			macroName:SetText("");
		end

		-- Save the action so we don't update in OnUpdate()
		this.action = pagedID;
	end
end

function PopBarButton_ShowGrid(button)
	if (not button) then
		button = this;
	end
	button.showgrid = 1;
	--getglobal(this:GetName().."NormalTexture"):SetVertexColor(1.0, 1.0, 1.0);
	--button:Show();
	PopBarButton_CheckShow(button);
end

function PopBarButton_HideGrid(button)
	if (not button) then
		button = this;
	end
	button.showgrid = 0;
	--if ( button.showgrid == 0 and not HasAction(PopBarButton_GetPagedID(button)) ) then
	--	button:Hide();
	--end
	PopBarButton_CheckShow(button);
end

function PopBarButton_UpdateState(button)
	if (not button) then
		button = this;
	end
	local pagedID = PopBarButton_GetPagedID(button);
	if (pagedID) then
		if ( IsCurrentAction(pagedID) or IsAutoRepeatAction(pagedID) ) then
			button:SetChecked(1);
		else
			button:SetChecked(0);
		end
	end
end

function PopBarButton_UpdateUsable(button)
	if (not button) then
		button = this;
	end
	local icon = getglobal(button:GetName().."Icon");
	local normalTexture = getglobal(button:GetName().."NormalTexture");
	local pagedID = PopBarButton_GetPagedID(button);
	local isUsable, notEnoughMana;
	if (pagedID) then
		isUsable, notEnoughMana = IsUsableAction(pagedID);
	end
	if (icon and normalTexture) then
		if ( isUsable ) then
			local inRange = true;
			if ( button.rangeTimer and (IsActionInRange(pagedID) == 0)) then
				inRange = false;
			end
			if ( inRange ) then
				icon:SetVertexColor(1.0, 1.0, 1.0);
				normalTexture:SetVertexColor(1.0, 1.0, 1.0);
			else
				icon:SetVertexColor(1.0, 0.5, 0.5);
				normalTexture:SetVertexColor(1.0, 0.5, 0.5);
			end
		elseif ( notEnoughMana ) then
			icon:SetVertexColor(0.5, 0.5, 1.0);
			normalTexture:SetVertexColor(0.5, 0.5, 1.0);
		else
			icon:SetVertexColor(0.4, 0.4, 0.4);
			normalTexture:SetVertexColor(1.0, 1.0, 1.0);
		end
	end
end

function PopBarButton_UpdateCount(button)
	if (not button) then
		button = this;
	end
	local text = getglobal(button:GetName().."Count");
	if ( not text ) then
		return;
	end
	local action = PopBarButton_GetPagedID(button);
	if ( IsConsumableAction(action) ) then
		text:SetText(GetActionCount(action));
	else
		text:SetText("");
	end
end

function PopBarButton_StartButtonCooldown(frame, start, duration, enable)
	local cooldownText = getglobal(frame:GetName().."CooldownCount");
	if not frame or not cooldownText then return; end

	if PopBar_Config.CooldownText == 1 and ( start > 0 and duration > 3 and enable > 0 ) then
		cooldownText.start = start
		cooldownText.duration = duration
		cooldownText.timeToNextUpdate = 0
		cooldownText.onCooldown = true
	else
		cooldownText:SetText("")
		cooldownText.onCooldown = false;
	end
end

function PopBarButton_UpdateButtonCooldown(frame, elapsed)
	local cooldownText = getglobal(frame:GetName().."CooldownCount");
	if not frame or not cooldownText then return; end
	if PopBar_Config.CooldownText == 0 then
		cooldownText:SetText("");
		cooldownText.onCooldown = false;
		return;
	end
	if ( cooldownText.onCooldown ) then
		if cooldownText.timeToNextUpdate <= 0 then
			local remain = cooldownText.duration - (GetTime() - cooldownText.start);
			if floor(remain + 0.5) > 0 then
				local text, toNextUpdate, scale = PopBarButton_FormatTime(remain);
				cooldownText:SetFont(STANDARD_TEXT_FONT, 24.5 * scale, "OUTLINE");
				cooldownText:Show();
				cooldownText:SetText(text);
				cooldownText.timeToNextUpdate = toNextUpdate;
			else
				cooldownText:SetText("");
				cooldownText.onCooldown = false;
			end
		else
			cooldownText.timeToNextUpdate = cooldownText.timeToNextUpdate - elapsed;
		end
	end
end

function PopBarButton_FormatTime(secs)
	if secs > 86400 then
		return floor(secs / 86400 + 0.5) .. POPBAR_DAY, mod(secs, 86400), 0.75;
	elseif secs > 3600 then
		return floor(secs / 3600 + 0.5) .. POPBAR_HOUR, mod(secs, 3600), 0.75;
	elseif secs > 60 then
		return floor(secs / 60 + 0.5) .. POPBAR_MINUTE, mod(secs, 60), 0.75;
	end
	return floor(secs + 0.5), secs - floor(secs), 1;
end

function PopBarButton_UpdateCooldown(button)
	if (not button) then
		button = this;
	end
	local row, col;
	if (string.len(button:GetID()) > 3) then
		_, _, row, col = string.find (button:GetID(), "(%d%d)(%d%d)");
	else
		_, _, row, col = string.find (button:GetID(), "(%d)(%d%d)");
	end
	local cooldown = getglobal(button:GetName().."Cooldown");
	local start, duration, enable = GetActionCooldown(PopBarButton_GetPagedID(button));
	CooldownFrame_SetTimer(cooldown, start, duration, enable);
	PopBarButton_StartButtonCooldown(button, start, duration, enable);
	row = tonumber(row);
	col = tonumber(col);
	if((row > PopBar_Config.RowShow) or (col > PopBar_Config.ColShow)) then
		if ( PopBar_Combat ) then
			cooldown:Hide();
		else
			cooldown:Show();
		end
	end
end

function PopBarButton_OnEvent(event)
	if ( event == "PLAYER_REGEN_DISABLED" ) then 
		PopBar_Combat = true; 
		PopBarButton_Update(); 
		return; 
	end 
	if ( event == "PLAYER_REGEN_ENABLED" ) then 
		PopBar_Combat = false; 
		PopBarButton_Update(); 
		return; 
	end 

	if ( event == "ACTIONBAR_SLOT_CHANGED" ) then
		if ( arg1 == -1 or arg1 == PopBarButton_GetPagedID(this) ) then
			PopBarButton_Update();
		end
		return;
	end
	if ( event == "ACTIONBAR_PAGE_CHANGED" ) then
		if (PopBar_Config.TurnPages==1) then
			local id = PopBarButton_GetPagedID(this);
			this:SetAttribute("action", id);
			PopBarButton_Update();
		end
		return;
	end
	if ( event == "PLAYER_ENTERING_WORLD" ) then
		PopBarButton_Update();
		return;
	end
	if ( event == "ACTIONBAR_SHOWGRID" ) then
		PopBarButton_ShowGrid();
		return;
	end
	if ( event == "ACTIONBAR_HIDEGRID" ) then
		PopBarButton_HideGrid();
		return;
	end
	if ( event == "UPDATE_BINDINGS" ) then
		PopBarButton_UpdateHotkeys();
		return;
	end

	-- All event handlers below this line MUST only be valid when the button is visible
	if ( not this:IsVisible() ) then
		return;
	end

	if ( event == "PLAYER_TARGET_CHANGED" or event == "PLAYER_AURAS_CHANGED" ) then
		PopBarButton_UpdateUsable();
		PopBarButton_UpdateHotkeys("POPBARBUTTON");
	elseif ( event == "UNIT_INVENTORY_CHANGED" ) then
		if ( arg1 == "player" ) then
			PopBarButton_Update();
		end
	elseif ( event == "ACTIONBAR_UPDATE_STATE" ) then
		PopBarButton_UpdateState();
	elseif ( event == "ACTIONBAR_UPDATE_USABLE" or event == "UPDATE_INVENTORY_ALERTS" or event == "ACTIONBAR_UPDATE_COOLDOWN" ) then
		PopBarButton_UpdateUsable();
		PopBarButton_UpdateCooldown();
	elseif ( event == "CRAFT_SHOW" or event == "CRAFT_CLOSE" or event == "TRADE_SKILL_SHOW" or event == "TRADE_SKILL_CLOSE" ) then
		PopBarButton_UpdateState();
	elseif ( event == "PLAYER_ENTER_COMBAT" ) then
		if ( IsAttackAction(PopBarButton_GetPagedID(this)) ) then
			PopBarButton_StartFlash();
		end
	elseif ( event == "PLAYER_LEAVE_COMBAT" ) then
		if ( IsAttackAction(PopBarButton_GetPagedID(this)) ) then
			PopBarButton_StopFlash();
		end
	elseif ( event == "START_AUTOREPEAT_SPELL" ) then
		if ( IsAutoRepeatAction(PopBarButton_GetPagedID(this)) ) then
			PopBarButton_StartFlash();
		end
	elseif ( event == "STOP_AUTOREPEAT_SPELL" ) then
		if ( PopBarButton_IsFlashing() and not IsAttackAction(PopBarButton_GetPagedID(this)) ) then
			PopBarButton_StopFlash();
		end
	end
end

function PopBarButton_SetTooltip(button)
	if (not button) then
		button = this;
	end

	if ((GetCVar("UberTooltips") == "1") and (not Cosmos_RelocateUberTooltip)) then
		GameTooltip_SetDefaultAnchor(GameTooltip, this);
	else
		if (SmartSetOwner) then
			SmartSetOwner(this);
		else
			GameTooltip:SetOwner(this,"ANCHOR_TOPRIGHT");
		end
	end

	if ( GameTooltip:SetAction(PopBarButton_GetPagedID(button)) ) then
		this.updateTooltip = TOOLTIP_UPDATE_TIME;
	else
		this.updateTooltip = nil;
	end
end

function PopBarButton_OnUpdate(elapsed)

	local hotkey = getglobal(this:GetName().."HotKey");
	local action = PopBarButton_GetPagedID(this);

	if ( this.action ~= action ) then
		PopBarButton_Update();
	end

	if ( hotkey:GetText() == RANGE_INDICATOR ) then
		if ( IsActionInRange(action) == 1 ) then
			hotkey:Hide();
		else
			hotkey:Show();
		end
	end

	if ( HasAction(action) ) then
		PopBarButton_UpdateButtonCooldown(this, elapsed);
	end

	if ( PopBarButton_IsFlashing() ) then
		this.flashtime = this.flashtime - elapsed;
		if ( this.flashtime <= 0 ) then
			local overtime = -this.flashtime;
			if ( overtime >= ATTACK_BUTTON_FLASH_TIME ) then
				overtime = 0;
			end
			this.flashtime = ATTACK_BUTTON_FLASH_TIME - overtime;

			local flashTexture = getglobal(this:GetName().."Flash");
			if ( flashTexture:IsShown() ) then
				flashTexture:Hide();
			else
				flashTexture:Show();
			end
		end
	end
	
	-- Handle range indicator
	if ( this.rangeTimer ) then
		if ( this.rangeTimer < 0 ) then
			PopBarButton_UpdateUsable(this);
			local count = getglobal(this:GetName().."HotKey");
			if (IsActionInRange(action) == 0) then
				count:SetVertexColor(1.0, 0.1, 0.1);
			else
				count:SetVertexColor(0.6, 0.6, 0.6);
			end
			this.rangeTimer = TOOLTIP_UPDATE_TIME;
		else
			this.rangeTimer = this.rangeTimer - elapsed;
		end
	else
		local count = getglobal(this:GetName().."HotKey");
		count:SetVertexColor(0.6, 0.6, 0.6);
	end

	if ( not this.updateTooltip ) then
		return;
	end

	this.updateTooltip = this.updateTooltip - elapsed;
	if ( this.updateTooltip > 0 ) then
		return;
	end

	if ( GameTooltip:IsOwned(this) ) then
		PopBarButton_SetTooltip();
	else
		this.updateTooltip = nil;
	end
end

function PopBarButton_GetPagedID(button)
	if( button == nil ) then
		message("nil button passed into PopBarButton_GetPagedID(), contact Jeff");
		return 0;
	end
	
	local row, col;
	if (string.len(button:GetID()) > 3) then
		_, _, row, col = string.find (button:GetID(), "(%d%d)(%d%d)");
	else
		_, _, row, col = string.find (button:GetID(), "(%d)(%d%d)");
	end
	local page = GetActionBarPage();
	if (PopBar_Config.TurnPages==0) then
		page = 1;
	end
	if (row and col) then
		row = tonumber(row);
		col = tonumber(col);
		local retid = 1;
		if (PopBar_Config.VAnchor==1) then
			row = POPBAR_MAX_ROWS - (row - 1);
		end
		if (PopBar_Config.FlipV==1) then
			row = PopBar_Config.Rows - (row - 1);
		end		
		if (PopBar_Config.HAnchor==1) then
			col = POPBAR_MAX_COLS - (col - 1);
		end
		if (PopBar_Config.FlipH==1) then
			col = PopBar_Config.Cols - (col - 1);
		end
		local butNum;
		if (PopBar_Config.Orient==1) then		
			butNum = (PopBar_Config.Rows * (col - 1)) + row;
		else
			butNum = (PopBar_Config.Cols * (row - 1)) + col;
		end
		if (PopBar_Config.IDUp == 1) then
			retid = butNum + (PopBar_StartID - 1) + ((page - 1) * 12);
		else
			retid = ((PopBar_StartID + 1) + ((page - 1) * 12)) - butNum;
		end
		if (retid > POPBAR_MAX_ID) then
			retid = retid + ((POPBAR_HIGH_ID - 1) - POPBAR_MAX_ID);
			if (retid > POPBAR_MAX_HIGH_ID) then
				retid = retid - POPBAR_MAX_HIGH_ID;
			end
		end
		if (retid < 1) then
			retid = POPBAR_MAX_HIGH_ID + retid;
			if (retid < POPBAR_HIGH_ID) then
				retid = retid - ((POPBAR_HIGH_ID - 1) - POPBAR_MAX_ID);
			end
		end
		if ( PopBar_Config.Cols < POPBAR_MAX_COLS and row > 1 ) then
			retid = retid - ((row - 1) * (POPBAR_MAX_COLS - PopBar_Config.Cols));
		end
		return retid;
	else
		return nil;
	end
end

function PopBarButton_UpdateFlash(button)
	if (not button) then
		button = this;
	end
	local action = PopBarButton_GetPagedID(button);
	if ( (IsAttackAction(action) and IsCurrentAction(action)) or IsAutoRepeatAction(action) ) then
		PopBarButton_StartFlash(button);
	else
		PopBarButton_StopFlash(button);
	end
end

function PopBarButton_StartFlash(button)
	if (not button) then
		button = this;
	end
	button.flashing = 1;
	button.flashtime = 0;
	PopBarButton_UpdateState();
end

function PopBarButton_StopFlash(button)
	if (not button) then
		button = this;
	end
	button.flashing = 0;
	getglobal(button:GetName().."Flash"):Hide();
	PopBarButton_UpdateState();
end

function PopBarButton_IsFlashing(button)
	if (not button) then
		button = this;
	end
	if ( button.flashing == 1 ) then
		return 1;
	else
		return nil;
	end
end

function PopBar_Show ( toggle ) 
	if(InCombatLockdown()) then 
		--DEFAULT_CHAT_FRAME:AddMessage(POPBAR_INCOMBAT_WARNING, 1, 0.83, 0);
		return;
	end
	if (toggle == -1) then
		if (PopBar_Config.Enabled == 1) then
			toggle = 0;
		else
			toggle = 1;
		end
	end
	if (toggle == 1) then 
		PopBar:Show();
		PopBarKnob:Show();
		PopBar_Config.Enabled = 1;
	else
		PopBar:Hide(); 
		PopBarKnob:Hide();
		PopBar_Config.Enabled = 0;
	end
end

function PopBar_OnLoad()
	this:RegisterEvent("PLAYER_ENTERING_WORLD");
	this:RegisterEvent("PLAYER_LEAVING_WORLD");

	if( PopBar_Initialized == 0) then
		MCom.registerVarsLoaded(PopBar_CosVarsLoaded);
		MCom.registerSmart( {
			uioption = {
				"COS_POPBAR",
				"SECTION",
				POPBAR_CONFIG_HEADER,
				POPBAR_CONFIG_HEADER_INFO
			};
			uifolder = "bars";
			uisecdiff = 1;
			addonname = "PopBar";
			name = POPBAR_CONFIG_HEADER;									--The name of the addon, for display in the info text
			supercom = {"/popbar", "/pb"};								--The main slash command, and any aliases for it
			comaction = "before";													--See Sky for info on this
			comsticky = false;														--See Sky for info on this
			comhelp = POPBAR_CHAT_COMMAND_INFO;						--The help text to show for the slash command
		} );
		MCom.registerSmart( {
			uioption = {
				"COS_POPBAR_TOGGLE", -- CVAr
				"CHECKBOX",
				POPBAR_CONFIG_ONOFF,
				POPBAR_CONFIG_ONOFF_INFO,
				nil,
				PopBar_Config.Enabled
			};
			uidiff = 1;
			uisep = "POPBAR_HEADER";
			uiseplabel = POPBAR_CONFIG_HEADER;
			uisepdesc = POPBAR_CONFIG_HEADER_INFO;
			uisepdiff = 1;
			varbool = "PopBar_Config.Enabled";							--The boolean variable associate with this option
			update = function ()	PopBar_Update(true);
				PopBar_Show(MCom.getStringVar("PopBar_Config.Enabled")); end;
			supercom = {"/popbar", "/pb"};								--The main slash command, and any aliases for it
			subcom = {"enable"};														--The sub slash command and any aliases for this option
		} );
		MCom.registerSmart( {
			uioption = {
				"COS_POPBAR_PAGES", -- CVAr
				"CHECKBOX",
				POPBAR_CONFIG_PAGES,
				POPBAR_CONFIG_PAGES_INFO,
				nil,
				PopBar_Config.TurnPages
			};
			uidiff = 2;
			varbool = "PopBar_Config.TurnPages";						--The boolean variable associate with this option
			update = function () PopBar_Initialize(); end;
			supercom = "/pb";																--The main(super) slash command associated with this subommand
			subcom = {"pages"};															--The sub slash command and any aliases for this option
		} );
		MCom.registerSmart( {
			uioption = {
				"COS_POPBAR_COOLDOWNTEXT", -- CVAr
				"CHECKBOX",
				POPBAR_CONFIG_COOLDOWNTEXT,
				POPBAR_CONFIG_COOLDOWNTEXT_INFO,
				nil,
				PopBar_Config.CooldownText
			};
			uidiff = 2;
			varbool = "PopBar_Config.CooldownText";						--The boolean variable associate with this option
			--update = function () PopBar_Initialize(); end;
			supercom = "/pb";																--The main(super) slash command associated with this subommand
			subcom = {"cooldown"};															--The sub slash command and any aliases for this option
		} );
		MCom.registerSmart( {
			uioption = {
				"COS_POPBAR_HIDEEMPTY", -- CVAr
				"CHECKBOX",
				POPBAR_CONFIG_HIDEEMPTY,
				POPBAR_CONFIG_HIDEEMPTY_INFO,
				nil,
				PopBar_Config.HideEmpty
			};
			uidiff = 1;
			varbool = "PopBar_Config.HideEmpty";						--The boolean variable associate with this option
			update = function () PopBar_Update(true); end;
			supercom = "/pb";																--The main(super) slash command associated with this subommand
			subcom = {"hideempty"};													--The sub slash command and any aliases for this option
		} );
		MCom.registerSmart( {
			uioption = {
				"COS_POPBAR_HIDEKEYS", -- CVAr
				"CHECKBOX",
				POPBAR_CONFIG_HIDEKEYS,
				POPBAR_CONFIG_HIDEKEYS_INFO,
				nil,
				PopBar_Config.HideKeys
			};
			uidiff = 2;
			varbool = "PopBar_Config.HideKeys";							--The boolean variable associate with this option
			update = function () PopBar_Update(true); end;
			supercom = "/pb";																--The main(super) slash command associated with this subommand
			subcom = {"hidekeys"};													--The sub slash command and any aliases for this option
		} );
		MCom.registerSmart( {
			uioption = {
				"COS_POPBAR_HIDEKEYMOD", -- CVAr
				"CHECKBOX",
				POPBAR_CONFIG_HIDEKEYMOD,
				POPBAR_CONFIG_HIDEKEYMOD_INFO,
				nil,
				PopBar_Config.HideKeyMod
			};
			uidiff = 2;
			varbool = "PopBar_Config.HideKeyMod";						--The boolean variable associate with this option
			update = function () PopBar_Update(true); end;
			supercom = "/pb";																--The main(super) slash command associated with this subommand
			subcom = {"hidekeymod"};												--The sub slash command and any aliases for this option
		} );
		MCom.registerSmart( {
			uioption = {
				"COS_POPBAR_ORIENT", -- CVAr
				"CHECKBOX",
				POPBAR_CONFIG_ORIENT,
				POPBAR_CONFIG_ORIENT_INFO,
				nil,
				PopBar_Config.Orient
			};
			uidiff = 1;
			varbool = "PopBar_Config.Orient";								--The boolean variable associate with this option
			update = function () PopBar_Update(true); end;
			supercom = "/pb";																--The main(super) slash command associated with this subommand
			subcom = {"orient"};														--The sub slash command and any aliases for this option
		} );
		MCom.registerSmart( {
			uioption = {
				"COS_POPBAR_AREA", -- CVAr
				"CHECKBOX",
				POPBAR_CONFIG_AREA,
				POPBAR_CONFIG_AREA_INFO,
				nil,
				PopBar_Config.InArea
			};
			uidiff = 1;
			varbool = "PopBar_Config.InArea";								--The boolean variable associate with this option
			update = function () PopBar_Update(true); end;
			supercom = "/pb";																--The main(super) slash command associated with this subommand
			subcom = {"area"};															--The sub slash command and any aliases for this option
		} );
		MCom.registerSmart( {
			uioption = {
				"COS_POPBAR_VANCHOR", -- CVAr
				"CHECKBOX",
				POPBAR_CONFIG_VANCHOR,
				POPBAR_CONFIG_VANCHOR_INFO,
				nil,
				PopBar_Config.VAnchor
			};
			uidiff = 2;
			varbool = "PopBar_Config.VAnchor";							--The boolean variable associate with this option
			update = function () PopBar_Update(true); end;
			supercom = "/pb";																--The main(super) slash command associated with this subommand
			subcom = {"vanchor"};														--The sub slash command and any aliases for this option
		} );
		MCom.registerSmart( {
			uioption = {
				"COS_POPBAR_HANCHOR", -- CVAr
				"CHECKBOX",
				POPBAR_CONFIG_HANCHOR,
				POPBAR_CONFIG_HANCHOR_INFO,
				nil,
				PopBar_Config.HAnchor
			};
			uidiff = 2;
			varbool = "PopBar_Config.HAnchor";							--The boolean variable associate with this option
			update = function () PopBar_Update(true); end;
			supercom = "/pb";																--The main(super) slash command associated with this subommand
			subcom = {"hanchor"};														--The sub slash command and any aliases for this option
		} );
		if (Chronos) then
			MCom.registerSmart( {
				uioption = {
					"COS_POPBAR_POPTIME", -- CVAr
					"SLIDER",
					POPBAR_CONFIG_POPTIME,
					POPBAR_CONFIG_POPTIME_INFO,
					nil,
					0,
					PopBar_Config.PopTime,
					0,
					POPBAR_MAX_POPTIME,
					POPBAR_CONFIG_POPTIME_NAME,
					0.1,
					1,
					POPBAR_CONFIG_POPTIME_SUFFIX,
					1
				};
				uidiff = 2;
				varnum = "PopBar_Config.PopTime";								--The boolean variable associate with this option
				update = function () PopBar_Update(true); end;
				supercom = "/pb";																--The main(super) slash command associated with this subommand
				subcom = {"poptime"};														--The sub slash command and any aliases for this option
			} );
		end
		MCom.registerSmart( {
			uioption = {
				"COS_POPBAR_SCALE", -- CVAr
				"SLIDER",
				POPBAR_CONFIG_SCALE,
				POPBAR_CONFIG_SCALE_INFO,
				nil,
				0,
				PopBar_Config.Scale,
				0,
				2,
				POPBAR_CONFIG_SCALE_NAME,
				0.01,
				1,
				POPBAR_CONFIG_SCALE_SUFFIX,
				1
			};
			uidiff = 1;
			varnum = "PopBar_Config.Scale";							--The boolean variable associate with this option
			update = function () PopBar_Initialize(); end;
			supercom = "/pb";																--The main(super) slash command associated with this subommand
			subcom = {"scale"};															--The sub slash command and any aliases for this option
		} );
		MCom.registerSmart( {
			uioption = {
				"COS_POPBAR_KNOBALPHA", -- CVAr
				"SLIDER",
				POPBAR_CONFIG_KNOBALPHA,
				POPBAR_CONFIG_KNOBALPHA_INFO,
				PopBar_SetKnobAlpha,
				0,
				nil,
				0,
				1,
				POPBAR_CONFIG_KNOBALPHA_NAME,
				0.01,
				1,
				POPBAR_CONFIG_KNOBALPHA_SUFFIX,
				100
			};
			setup={
				sliderStep=5;
				sliderText=OFFSET;
				sliderMin=0;
				sliderMax=200;
				};

			uidiff = 1;
			varnum = "PopBar_Config.KnobAlpha";							--The boolean variable associate with this option
			update = function () PopBar_Update(true); end;
			supercom = "/pb";																--The main(super) slash command associated with this subommand
			subcom = {"knobalpha"};													--The sub slash command and any aliases for this option
		} );
		MCom.registerSmart( {
			uioption = {
				"COS_POPBAR_BARALPHA", -- CVAr
				"SLIDER",
				POPBAR_CONFIG_BARALPHA,
				POPBAR_CONFIG_BARALPHA_INFO,
				nil,
				0,
				PopBar_Config.BarAlpha,
				0,
				1,
				POPBAR_CONFIG_BARALPHA_NAME,
				0.01,
				1,
				POPBAR_CONFIG_BARALPHA_SUFFIX,
				100
			};
			uidiff = 1;
			varnum = "PopBar_Config.BarAlpha";							--The boolean variable associate with this option
			update = function () PopBar_Update(true); end;
			supercom = "/pb";																--The main(super) slash command associated with this subommand
			subcom = {"alpha"};															--The sub slash command and any aliases for this option
		} );
		MCom.registerSmart( {
			uioption = {
				"COS_POPBAR_ROWS", -- CVAr
				"SLIDER",
				POPBAR_CONFIG_ROWS,
				POPBAR_CONFIG_ROWS_INFO,
				nil,
				0,
				PopBar_Config.Rows,
				1,
				POPBAR_MAX_ROWS,
				POPBAR_CONFIG_ROWS_NAME,
				1,
				1,
				POPBAR_CONFIG_ROWS_SUFFIX,
				1				
			};
			uidiff = 1;
			varnum = "PopBar_Config.Rows";								--The boolean variable associate with this option
			update = function () PopBar_SetRows(nil, MCom.getStringVar("PopBar_Config.Rows")); end;
			supercom = "/pb";															--The main(super) slash command associated with this subommand
			subcom = {"rows"};														--The sub slash command and any aliases for this option
		} );
		MCom.registerSmart( {
			uioption = {
				"COS_POPBAR_COLS", -- CVAr
				"SLIDER",
				POPBAR_CONFIG_COLS,
				POPBAR_CONFIG_COLS_INFO,
				nil,
				0,
				PopBar_Config.Cols,
				1,
				POPBAR_MAX_COLS,
				POPBAR_CONFIG_COLS_NAME,
				1,
				1,
				POPBAR_CONFIG_COLS_SUFFIX,
				1				
			};
			uidiff = 1;
			varnum = "PopBar_Config.Cols";								--The boolean variable associate with this option
			update = function () PopBar_SetCols(nil, MCom.getStringVar("PopBar_Config.Cols")); end;
			supercom = "/pb";															--The main(super) slash command associated with this subommand
			subcom = {"cols"};														--The sub slash command and any aliases for this option
		} );
		MCom.registerSmart( {
			uioption = {
				"COS_POPBAR_ROWSHOW", -- CVAr
				"SLIDER",
				POPBAR_CONFIG_ROWSHOW,
				POPBAR_CONFIG_ROWSHOW_INFO,
				nil,
				0,
				PopBar_Config.RowShow,
				0,
				POPBAR_MAX_ROWS,
				POPBAR_CONFIG_ROWSHOW_NAME,
				1,
				1,
				POPBAR_CONFIG_ROWSHOW_SUFFIX,
				1				
			};
			uidiff = 1;
			varnum = "PopBar_Config.RowShow";								--The boolean variable associate with this option
			update = function () PopBar_SetRowShow(nil, MCom.getStringVar("PopBar_Config.RowShow")); end;
			supercom = "/pb";																--The main(super) slash command associated with this subommand
			subcom = {"srows"};															--The sub slash command and any aliases for this option
		} );
		MCom.registerSmart( {
			uioption = {
				"COS_POPBAR_COLSHOW", -- CVAr
				"SLIDER",
				POPBAR_CONFIG_COLSHOW,
				POPBAR_CONFIG_COLSHOW_INFO,
				nil,
				0,
				PopBar_Config.ColShow,
				0,
				POPBAR_MAX_COLS,
				POPBAR_CONFIG_COLSHOW_NAME,
				1,
				1,
				POPBAR_CONFIG_COLSHOW_SUFFIX,
				1				
			};
			uidiff = 1;
			varnum = "PopBar_Config.ColShow";								--The boolean variable associate with this option
			update = function () PopBar_SetColShow(nil, MCom.getStringVar("PopBar_Config.ColShow")); end;
			supercom = "/pb";																--The main(super) slash command associated with this subommand
			subcom = {"scols"};															--The sub slash command and any aliases for this option
		} );
		MCom.registerSmart( {
			uioption = {
				"COS_POPBAR_IDUP", -- CVAr
				"CHECKBOX",
				POPBAR_CONFIG_IDUP,
				POPBAR_CONFIG_IDUP_INFO,
				nil,
				PopBar_Config.IDUp
			};
			uidiff = 3;
			varbool = "PopBar_Config.IDUp";									--The boolean variable associate with this option
			update = function () PopBar_Initialize(); end;
			supercom = "/pb";																--The main(super) slash command associated with this subommand
			subcom = {"idup"};															--The sub slash command and any aliases for this option
		} );
		MCom.registerSmart( {
			uioption = {
				"COS_POPBAR_FLIPH", -- CVAr
				"CHECKBOX",
				POPBAR_CONFIG_FLIPH,
				POPBAR_CONFIG_FLIPH_INFO,
				nil,
				PopBar_Config.FlipH
			};
			uidiff = 3;
			varbool = "PopBar_Config.FlipH";								--The boolean variable associate with this option
			update = function () PopBar_Initialize(); end;
			supercom = "/pb";																--The main(super) slash command associated with this subommand
			subcom = {"fliph"};															--The sub slash command and any aliases for this option
		} );
		MCom.registerSmart( {
			uioption = {
				"COS_POPBAR_FLIPV", -- CVAr
				"CHECKBOX",
				POPBAR_CONFIG_FLIPV,
				POPBAR_CONFIG_FLIPV_INFO,
				nil,
				PopBar_Config.FlipV
			};
			uidiff = 3;
			varbool = "PopBar_Config.FlipV";								--The boolean variable associate with this option
			update = function () PopBar_Initialize(); end;
			supercom = "/pb";																--The main(super) slash command associated with this subommand
			subcom = {"flipv"};															--The sub slash command and any aliases for this option
		} );
		MCom.registerSmart( {
			uioption = {
				"COS_POPBAR_STARTPAGE", -- CVAr
				"SLIDER",
				POPBAR_CONFIG_STARTPAGE,
				POPBAR_CONFIG_STARTPAGE_INFO,
				nil,
				0,
				PopBar_Config.StartPage,
				1,
				POPBAR_MAX_BARS,
				POPBAR_CONFIG_STARTPAGE_NAME,
				1,
				1,
				POPBAR_CONFIG_STARTPAGE_SUFFIX,
				1
			};
			uidiff = 3;
			varnum = "PopBar_Config.StartPage";							--The boolean variable associate with this option
			update = function () PopBar_Initialize(); end;
			supercom = "/pb";																--The main(super) slash command associated with this subommand
			subcom = {"startpage"};													--The sub slash command and any aliases for this option
		} );
		MCom.registerSmart( {
			uioption = {
				"COS_POPBAR_STARTBUTTON", -- CVAr
				"SLIDER",
				POPBAR_CONFIG_STARTBUTTON,
				POPBAR_CONFIG_STARTBUTTON_INFO,
				nil,
				0,
				PopBar_Config.StartButton,
				1,
				12,
				POPBAR_CONFIG_STARTBUTTON_NAME,
				1,
				1,
				POPBAR_CONFIG_STARTBUTTON_SUFFIX,
				1				
			};
			uidiff = 3;
			varnum = "PopBar_Config.StartButton";						--The boolean variable associate with this option
			update = function () PopBar_Initialize(); end;
			supercom = "/pb";																--The main(super) slash command associated with this subommand
			subcom = {"startbutton"};												--The sub slash command and any aliases for this option
		} );
		MCom.registerSmart( {
			uioption = {
				"COS_POPBAR_RESET", -- CVAr
				"BUTTON",
				POPBAR_CONFIG_RESET,
				POPBAR_CONFIG_RESET_INFO,
				PopBar_ResetPos,
				0,
				0,
				0,
				0,
				POPBAR_CONFIG_RESET_NAME
			};
			uidiff = 2;
			supercom = "/pb";																--The main(super) slash command associated with this subommand
			subcom = {"reset"};															--The sub slash command and any aliases for this option
		} );
				
		PopBar_Config.Cols=1;
		PopBar_Config.Rows=1;
		PopBar_Initialized = 1;
	end
end

function PopBar_OnEvent()
	if ( event == "PLAYER_ENTERING_WORLD" ) then
		this:RegisterEvent("UPDATE_BINDINGS")
		if ( not PopBar_ConvertDone ) then
			PopBar_ConvertBindings();
			PopBar_RegisterBindings();
			PopBar_ConvertDone = true;
		end
	elseif ( event == "UPDATE_BINDINGS" ) then
		PopBar_RegisterBindings();
	elseif ( event == "PLAYER_LEAVING_WORLD" ) then
		this:UnregisterEvent("UPDATE_BINDINGS")
	end
end

function PopBar_ConvertBindings()
	for row=1, POPBAR_MAX_ROWS do
		for i=1, POPBAR_MAX_COLS do
			local key1, key2;
			if ( i > 9 ) then
				key1, key2 = GetBindingKey("CLICK PopBarButton"..row..i..":LeftButton");
				if key1 then SetBinding(key1, "POPBARBUTTON" .. row .. i); end
				if key2 then SetBinding(key2, "POPBARBUTTON" .. row .. i); end
			else
				key1, key2 = GetBindingKey("CLICK PopBarButton"..row.."0"..i..":LeftButton");
				if key1 then SetBinding(key1, "POPBARBUTTON" .. row .. "0" .. i); end
				if key2 then SetBinding(key2, "POPBARBUTTON" .. row .. "0" .. i); end
			end
		end
	end
	SaveBindings(GetCurrentBindingSet());
end

function PopBar_RegisterBindings()
	ClearOverrideBindings(PopBar);
	for row=1, POPBAR_MAX_ROWS do
		for i=1, POPBAR_MAX_COLS do
			local key1, key2;
			if ( i > 9 ) then
				key1, key2 = GetBindingKey("POPBARBUTTON"..row..i)
				if key1 then SetOverrideBindingClick(PopBar, false, key1, "PopBarButton" .. row .. i); end
				if key2 then SetOverrideBindingClick(PopBar, false, key2, "PopBarButton" .. row .. i); end
			else
				key1, key2 = GetBindingKey("POPBARBUTTON"..row.."0"..i)
				if key1 then SetOverrideBindingClick(PopBar, false, key1, "PopBarButton" .. row .. "0" .. i); end
				if key2 then SetOverrideBindingClick(PopBar, false, key2, "PopBarButton" .. row .. "0" .. i); end
			end
		end
	end
end

function PopBar_CosVarsLoaded()
	PopBar_Initialize();
	PopBar_Loaded = true;

	--Use MCom's load function to load the config
	MCom.loadConfig( {
		configVar = "PopBar_Config";
		nonUIList = {};
	});
	PopBar_Show(PopBar_Config.Enabled);
	PopBar_Update(true);
end