-- globals
 MULTICASTACTIONBAR_SLIDETIME = 0.09;
 MULTICASTACTIONBAR_YPOS = 0;
 MULTICASTACTIONBAR_XPOS = 30;
 NUM_MULTI_CAST_PAGES = 3;
 NUM_MULTI_CAST_BUTTONS_PER_PAGE = 4;		-- NOTE: must match MAX_TOTEMS!!!
 
 -- locals
 local MULTI_CAST_FLYOUT_BUTTON_INITIAL_OFFSET = 4;
 local MULTI_CAST_FLYOUT_BUTTON_OFFSET = 2;
 local MULTI_CAST_FLYOUT_CLOSE_SEC = 3;
 
 local SLOT_EMPTY_TCOORDS = {
 	[EARTH_TOTEM_SLOT] = {
 		left	= 66 / 128,
 		right	= 96 / 128,
 		top		= 3 / 256,
 		bottom	= 33 / 256,
 	},
 	[FIRE_TOTEM_SLOT] = {
 		left	= 67 / 128,
 		right	= 97 / 128,
 		top		= 100 / 256,
 		bottom	= 130 / 256,
 	},
 	[WATER_TOTEM_SLOT] = {
 		left	= 39 / 128,
 		right	= 69 / 128,
 		top		= 209 / 256,
 		bottom	= 239 / 256,
 	},
 	[AIR_TOTEM_SLOT] = {
 		left	= 66 / 128,
 		right	= 96 / 128,
 		top		= 36 / 256,
 		bottom	= 66 / 256,
 	},
 };
 local SLOT_OVERLAY_TCOORDS = {
 	[EARTH_TOTEM_SLOT] = {
 		left	= 1 / 128,
 		right	= 35 / 128,
 		top		= 172 / 256,
 		bottom	= 206 / 256,
 	},
 	[FIRE_TOTEM_SLOT] = {
 		left	= 36 / 128,
 		right	= 70 / 128,
 		top		= 172 / 256,
 		bottom	= 206 / 256,
 	},
 	[WATER_TOTEM_SLOT] = {
 		left	= 1 / 128,
 		right	= 35 / 128,
 		top		= 207 / 256,
 		bottom	= 240 / 256,
 	},
 	[AIR_TOTEM_SLOT] = {
 		left	= 36 / 128,
 		right	= 70 / 128,
 		top		= 137 / 256,
 		bottom	= 171 / 256,
 	},
 };
 
 local FLYOUT_UP_BUTTON_TCOORDS = {
 	["summon"] = {
 		left	= 99 / 128,
 		right	= 127 / 128,
 		top		= 84 / 256,
 		bottom	= 102 / 256,
 	},
 	[EARTH_TOTEM_SLOT] = {
 		left	= 99 / 128,
 		right	= 127 / 128,
 		top		= 160 / 256,
 		bottom	= 178 / 256,
 	},
 	[FIRE_TOTEM_SLOT] = {
 		left	= 99 / 128,
 		right	= 127 / 128,
 		top		= 122 / 256,
 		bottom	= 140 / 256,
 	},
 	[WATER_TOTEM_SLOT] = {
 		left	= 99 / 128,
 		right	= 127 / 128,
 		top		= 199 / 256,
 		bottom	= 217 / 256,
 	},
 	[AIR_TOTEM_SLOT] = {
 		left	= 99 / 128,
 		right	= 127 / 128,
 		top		= 237 / 256,
 		bottom	= 255 / 256,
 	},
 };
 local FLYOUT_DOWN_BUTTON_TCOORDS = {
 	["summon"] = {
 		left	= 99 / 128,
 		right	= 127 / 128,
 		top		= 65 / 256,
 		bottom	= 83 / 256,
 	},
 	[EARTH_TOTEM_SLOT] = {
 		left	= 99 / 128,
 		right	= 127 / 128,
 		top		= 141 / 256,
 		bottom	= 159 / 256,
 	},
 	[FIRE_TOTEM_SLOT] = {
 		left	= 99 / 128,
 		right	= 127 / 128,
 		top		= 103 / 256,
 		bottom	= 121 / 256,
 	},
 	[WATER_TOTEM_SLOT] = {
 		left	= 99 / 128,
 		right	= 127 / 128,
 		top		= 180 / 256,
 		bottom	= 198 / 256,
 	},
 	[AIR_TOTEM_SLOT] = {
 		left	= 99 / 128,
 		right	= 127 / 128,
 		top		= 218 / 256,
 		bottom	= 236 / 256,
 	},
 };
 local FLYOUT_TOP_TCOORDS = {
 	["summon"] = {
 		left	= 33 / 128,
 		right	= 65 / 128,
 		top		= 1 / 256,
 		bottom	= 23 / 256,
 	},
 	[EARTH_TOTEM_SLOT] = {
 		left	= 0 / 128,
 		right	= 32 / 128,
 		top		= 46 / 256,
 		bottom	= 68 / 256,
 	},
 	[FIRE_TOTEM_SLOT] = {
 		left	= 33 / 128,
 		right	= 65 / 128,
 		top		= 46 / 256,
 		bottom	= 68 / 256,
 	},
 	[WATER_TOTEM_SLOT] = {
 		left	= 0 / 128,
 		right	= 32 / 128,
 		top		= 1 / 256,
 		bottom	= 23 / 256,
 	},
 	[AIR_TOTEM_SLOT] = {
 		left	= 0 / 128,
 		right	= 32 / 128,
 		top		= 91 / 256,
 		bottom	= 113 / 256,
 	},
 };
 local FLYOUT_MIDDLE_TCOORDS = {
 	["summon"] = {
 		left	= 33 / 128,
 		right	= 65 / 128,
 		top		= 23 / 256,
 		bottom	= 43 / 256,
 	},
 	[EARTH_TOTEM_SLOT] = {
 		left	= 0 / 128,
 		right	= 32 / 128,
 		top		= 68 / 256,
 		bottom	= 88 / 256,
 	},
 	[FIRE_TOTEM_SLOT] = {
 		left	= 33 / 128,
 		right	= 65 / 128,
 		top		= 68 / 256,
 		bottom	= 88 / 256,
 	},
 	[WATER_TOTEM_SLOT] = {
 		left	= 0 / 128,
 		right	= 32 / 128,
 		top		= 23 / 256,
 		bottom	= 43 / 256,
 	},
 	[AIR_TOTEM_SLOT] = {
 		left	= 0 / 128,
 		right	= 32 / 128,
 		top		= 113 / 256,
 		bottom	= 133 / 256,
 	},
 };
 
 -- knownMultiCastSummonSpells
 -- index: TOTEM_MULTI_CAST_SUMMON_SPELLS 
 -- value: spellId if the spell is known, nil otherwise
 local knownMultiCastSummonSpells = { };
 -- knownMultiCastRecallSpells
 -- index: TOTEM_MULTI_CAST_RECALL_SPELLS 
 -- value: spellId if the spell is known, nil otherwise
 local knownMultiCastRecallSpells = { };
 
 local function _ComputeMultiCastSlot(id)
 	return mod(id - 1, NUM_MULTI_CAST_BUTTONS_PER_PAGE) + 1;
 end
 
 --
 -- MultiCastActionBar
 --
 
 function MultiCastActionBarFrame_OnLoad(self)
 	self:RegisterEvent("PLAYER_ENTERING_WORLD");
 	self:RegisterEvent("UPDATE_MULTI_CAST_ACTIONBAR");
 
 	self.currentPage = 1;
 	MultiCastSummonSpellButton:SetID(self.currentPage);
 
 	self.numActiveSlots = 0;
 end
 
 function MultiCastActionBarFrame_OnEvent(self, event, ...)
 	if ( event == "PLAYER_ENTERING_WORLD" or event == "UPDATE_MULTI_CAST_ACTIONBAR" ) then
 		MultiCastActionBarFrame_Update(self);
 		if ( HasMultiCastActionBar() ) then
 			ShowMultiCastActionBar();
 			LockMultiCastActionBar();
 		else
 			UnlockMultiCastActionBar();
 			HideMultiCastActionBar();
 		end
 	end
 end
 
 function MultiCastActionBarFrame_OnUpdate(self, elapsed)
 	local yPos;
 	if ( self.slideTimer and (self.slideTimer < self.timeToSlide) ) then
 		self.completed = false;
 		if ( self.mode == "show" ) then
 			yPos = (self.slideTimer/self.timeToSlide) * MULTICASTACTIONBAR_YPOS;
 			self:SetPoint("BOTTOMLEFT", self:GetParent(), "TOPLEFT", MULTICASTACTIONBAR_XPOS, yPos);
 			self.state = "showing";
 			self:Show();
 		elseif ( self.mode == "hide" ) then
 			yPos = (1 - (self.slideTimer/self.timeToSlide)) * MULTICASTACTIONBAR_YPOS;
 			self:SetPoint("BOTTOMLEFT", self:GetParent(), "TOPLEFT", MULTICASTACTIONBAR_XPOS, yPos);
 			self.state = "hiding";
 		end
 		self.slideTimer = self.slideTimer + elapsed;
 	else
 		self.completed = true;
 		if ( self.mode == "show" ) then
 			self:SetPoint("BOTTOMLEFT", self:GetParent(), "TOPLEFT", MULTICASTACTIONBAR_XPOS, MULTICASTACTIONBAR_YPOS);
 			self.state = "top";
 			--Move the chat frame and edit box up a bit
 		elseif ( self.mode == "hide" ) then
 			self:SetPoint("BOTTOMLEFT", self:GetParent(), "TOPLEFT", MULTICASTACTIONBAR_XPOS, 0);
 			self.state = "bottom";
 			self:Hide();
 			--Move the chat frame and edit box back down to original position
 		end
 		self.mode = "none";
 	end
 end
 
 function ShowMultiCastActionBar(doNotSlide)
 	if ( (not MainMenuBar.busy) and (not UnitHasVehicleUI("player")) ) then	--Don't change while we're animating out MainMenuBar for vehicle UI
 		if ( (MultiCastActionBarFrame.mode ~= "show" and MultiCastActionBarFrame.state ~= "top") or (not UIParent:IsShown())) then
 			MultiCastActionBarFrame:Show();
 			if ( MultiCastActionBarFrame.completed ) then
 				MultiCastActionBarFrame.slideTimer = 0;
 			end
 			MultiCastActionBarFrame.timeToSlide = MULTICASTACTIONBAR_SLIDETIME;
 			MultiCastActionBarFrame.mode = "show";
 		end
 	end
 end
 
 function HideMultiCastActionBar()
 	if ( (not MainMenuBar.busy) and (not UnitHasVehicleUI("player")) ) then	--Don't change while we're animating out MainMenuBar for vehicle UI
 		if ( (MultiCastActionBarFrame:IsShown()) or (not UIParent:IsShown())) then
 			if ( MultiCastActionBarFrame.completed ) then
 				MultiCastActionBarFrame.slideTimer = 0;
 			end
 			MultiCastActionBarFrame.timeToSlide = MULTICASTACTIONBAR_SLIDETIME;
 			MultiCastActionBarFrame.mode = "hide";
 		end
 	end
 end
 
 function LockMultiCastActionBar()
 	MultiCastActionBarFrame.locked = true;
 end
 
 function UnlockMultiCastActionBar()
 	MultiCastActionBarFrame.locked = false;
 end
 
 function MultiCastActionBarFrame_Update(self)
 	local currentPage = self.currentPage;
 
 	-- update the action buttons and slot buttons
 	local slot;
 	local actionButton, slotButton;
 	local actionIndex;
 	local slotIndex = 1;
 	local inverseSlotIndex;
 	local pageOffset;
 	local actionId;
 	for i = 1, NUM_MULTI_CAST_BUTTONS_PER_PAGE do
 		slot = SHAMAN_TOTEM_PRIORITIES[i];
 		if ( GetTotemInfo(slot) and GetMultiCastTotemSpells(slot) ) then
 			-- update the slot button
 			slotButton = _G["MultiCastSlotButton"..slotIndex];
 			MultiCastSlotButton_Update(slotButton, slot);
 			-- update the action buttons using this totem slot on each page
 			for j = 1, NUM_MULTI_CAST_PAGES do
 				pageOffset = (j-1) * NUM_MULTI_CAST_BUTTONS_PER_PAGE;
 				actionIndex = pageOffset + slotIndex;
 				actionButton = _G["MultiCastActionButton"..actionIndex];
 				actionButton.slotButton = slotButton;
 				actionId = pageOffset + slot;
 				MultiCastActionButton_Update(actionButton, actionId, actionIndex, slot);
 				-- if this is the current page, store a reference to the action button on the slot button
 				if ( j == currentPage ) then
 					slotButton.actionButton = actionButton;
 				end
 			end
 			slotIndex = slotIndex + 1;
 		else
 			inverseSlotIndex = NUM_MULTI_CAST_BUTTONS_PER_PAGE - i + slotIndex;
 			-- hide the slot button
 			slotButton = _G["MultiCastSlotButton"..inverseSlotIndex];
 			MultiCastSlotButton_Update(slotButton, 0);
 			-- hide the action buttons for this button index on each page
 			for j = 1, NUM_MULTI_CAST_PAGES do
 				pageOffset = (j-1) * NUM_MULTI_CAST_BUTTONS_PER_PAGE;
 				actionIndex = pageOffset + inverseSlotIndex;
 				actionButton = _G["MultiCastActionButton"..actionIndex];
 				actionButton.slotButton = nil;
 				actionId = pageOffset + slot;
 				MultiCastActionButton_Update(actionButton, actionId, actionIndex, 0);
 			end
 			slotButton.actionButton = nil;
 		end
 	end
 
 	self.numActiveSlots = slotIndex - 1;
 	if ( self.numActiveSlots == 0 ) then
 		self:Hide();
 		return;
 	end
 	self:Show();
 
 	-- update the multi cast spells
 	MultiCastSummonSpellButton_Update(MultiCastSummonSpellButton);
 	MultiCastRecallSpellButton_Update(MultiCastRecallSpellButton);
 end
 
 function HasMultiCastActionBar()
 	return MultiCastActionBarFrame.numActiveSlots and MultiCastActionBarFrame.numActiveSlots > 0;
 end
 
 function HasMultiCastActionPage(page)
 	return ( page >= 1 and page <= NUM_MULTI_CAST_PAGES and knownMultiCastSummonSpells[page] );
 end
 
 function ChangeMultiCastActionPage(page)
 	local prevPage = MultiCastActionBarFrame.currentPage;
 	if ( page ~= prevPage and HasMultiCastActionPage(page) ) then
 		MultiCastActionBarFrame.currentPage = page;
 		MultiCastSummonSpellButton:SetID(page);
 		_G["MultiCastActionPage"..prevPage]:Hide();
 		_G["MultiCastActionPage"..page]:Show();
 		MultiCastActionBarFrame_Update(MultiCastActionBarFrame);
 	end
 end
 
 
 --
 -- MultiCastSlotButton
 --
 
 
 function MultiCastSlotButton_OnEvent(self, event, ...)
 	if ( event == "MODIFIER_STATE_CHANGED" ) then
 		if ( IsModifiedClick("SHOWMULTICASTFLYOUT") and self:IsMouseOver() ) then
 			MultiCastSlotButton_OnEnter(self);
 		end
 	end
 end
 
 function MultiCastSlotButton_OnEnter(self)
 	if ( MultiCastFlyoutFrame.parent ~= self ) then
 		MultiCastFlyoutFrameOpenButton_Show(MultiCastFlyoutFrameOpenButton, "slot", self);
 	end
 --[[
 	self:RegisterEvent("MODIFIER_STATE_CHANGED");
 	if ( IsModifiedClick("SHOWMULTICASTFLYOUT") ) then
 		local slot = self:GetID();
 		MultiCastFlyoutFrame_ToggleFlyout(MultiCastFlyoutFrame, "slot", self);
 	end
 --]]
 end
 
 function MultiCastSlotButton_OnLeave(self)
 	GameTooltip:Hide();
 	MultiCastFlyoutFrameOpenButton_Hide(MultiCastFlyoutFrameOpenButton);
 end
 
 function MultiCastSlotButton_Update(self, slot)
 	self:SetID(slot);
 	if ( slot == 0 ) then
 		self:Hide();
 	else
 		-- fixup textures
 		local tcoords = SLOT_OVERLAY_TCOORDS[slot];
 		self.overlayTex:SetTexCoord(tcoords.left, tcoords.right, tcoords.top, tcoords.bottom);
 		tcoords = SLOT_EMPTY_TCOORDS[slot];
 		self.background:SetTexCoord(tcoords.left, tcoords.right, tcoords.top, tcoords.bottom);
 
 		self:Show();
 	end
 end
 
 
 --
 -- MultiCastActionButton
 --
 
 function MultiCastActionButton_OnLoad(self)
 	-- fixup textures
 	local name = self:GetName();
 	local normalTexture = _G[name.."NormalTexture"];
 	normalTexture:SetWidth(50);
 	normalTexture:SetHeight(50);
 
 	-- setup action button stuff
 	self.buttonType = "MULTICASTACTIONBUTTON";
 	self.buttonIndex = self:GetID();
 	ActionButton_OnLoad(self);
 end
 
 function MultiCastActionButton_OnEvent(self, event, ...)
 	ActionButton_OnEvent(self, event, ...);
 	if ( event == "MODIFIER_STATE_CHANGED" ) then
 		if ( IsModifiedClick("SHOWMULTICASTFLYOUT") and self:IsMouseOver() ) then
 			MultiCastActionButton_OnEnter(self);
 		end
 	end
 end
 
 function MultiCastActionButton_OnShow(self)
 	if ( not self.slotButton ) then
 		self:Hide();
 	end
 end
 
 function MultiCastActionButton_OnEnter(self)
 	MultiCastSlotButton_OnEnter(self.slotButton);
 	ActionButton_SetTooltip(self);
 end
 
 function MultiCastActionButton_OnLeave(self)
 	GameTooltip:Hide();
 	MultiCastFlyoutFrameOpenButton_Hide(MultiCastFlyoutFrameOpenButton);
 end
 
 function MultiCastActionButton_OnPostClick(self, button, down)
 	ActionButton_UpdateState(self, button, down);
 	MultiCastFlyoutFrame_Hide(MultiCastFlyoutFrame, true);
 end
 
 function MultiCastActionButton_Update(self, id, index, slot)
 	self:SetID(id);
 	self.buttonIndex = index;
 	if ( slot == 0 ) then
 		self:Hide();
 	else
 		ActionButton_UpdateAction(self);
 		ActionButton_Update(self);
 		ActionButton_UpdateHotkeys(self, self.buttonType);
 
 		-- fixup textures
 		local tcoords;
 		tcoords = SLOT_OVERLAY_TCOORDS[slot];
 		self.overlayTex:SetTexCoord(tcoords.left, tcoords.right, tcoords.top, tcoords.bottom);
 		self:Show();
 	end
 end
 
 function MultiCastActionButtonDown(id)
 	local button = _G["MultiCastActionButton"..id];
 	if ( button:GetButtonState() == "NORMAL" ) then
 		button:SetButtonState("PUSHED");
 	end
 	if (GetCVarBool("ActionButtonUseKeyDown")) then
 		SecureActionButton_OnClick(button, "LeftButton");
 		ActionButton_UpdateState(button);
 	end
 end
 
 function MultiCastActionButtonUp(id)
 	local button = _G["MultiCastActionButton"..id];
 	if ( button:GetButtonState() == "PUSHED" ) then
 		button:SetButtonState("NORMAL");
 		if (not GetCVarBool("ActionButtonUseKeyDown")) then
 			SecureActionButton_OnClick(button, "LeftButton");
 			ActionButton_UpdateState(button);
 		end
 	end
 	MultiCastFlyoutFrame_Hide(MultiCastFlyoutFrame, true);
 end
 
 
 --
 -- MultiCastFlyoutButton
 --
 
 function MultiCastFlyoutButton_OnLoad(self)
 	self:RegisterForClicks("AnyUp");
 
 	local parent = self:GetParent();
 	tinsert(parent.buttons, self);
 end
 
 function MultiCastFlyoutButton_OnClick(self)
 	local parent = self:GetParent();
 
 	if ( self.spellId ) then
 		local type = parent.type;
 		if ( type == "page" ) then
 			ChangeMultiCastActionPage(self.page);
 		elseif ( type == "slot" ) then
 			SetMultiCastSpell(ActionButton_CalculateAction(parent.parent.actionButton), self.spellId);
 		end
 	end
 
 	MultiCastFlyoutFrame_Hide(parent, true);
 end
 
 function MultiCastFlyoutButton_OnEnter(self)
 	MultiCastFlyoutButton_SetTooltip(self);
 end
 
 function MultiCastFlyoutButton_OnLeave(self)
 	GameTooltip:Hide();
 end
 
 function MultiCastFlyoutButton_SetTooltip(self)
 	if ( self.spellId ) then
 		if ( self.spellId == 0 ) then
 			if ( GetCVarBool("UberTooltips") ) then
 				GameTooltip_SetDefaultAnchor(GameTooltip, self);
 			else
 				GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
 			end
 			GameTooltip:SetText(MULTI_CAST_TOOLTIP_NO_TOTEM, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b);
 			self.UpdateTooltip = nil;
 		else
 			if ( GetCVarBool("UberTooltips") ) then
 				GameTooltip_SetDefaultAnchor(GameTooltip, self);
 			else
 				GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
 			end
 			if ( GameTooltip:SetSpellByID(self.spellId, false, true) ) then
 				self.UpdateTooltip = MultiCastFlyoutButton_SetTooltip;
 			else
 				self.UpdateTooltip = nil;
 			end
 		end
 	end
 end
 
 
 --
 -- MultiCastFlyoutFrame
 --
 
 function MultiCastFlyoutFrame_OnShow(self)
 	MultiCastFlyoutFrameOpenButton_Hide(MultiCastFlyoutFrameOpenButton, true);
 end
 
 function MultiCastFlyoutFrame_OnHide(self)
 	self.type = nil;
 	self.parent = nil;
 end
 
 function MultiCastFlyoutFrame_OnEnter(self)
 end
 
 function MultiCastFlyoutFrame_OnLeave(self)
 --[[
 	if ( not self:IsMouseOver() ) then
 		self.closeCountdownSec = MULTI_CAST_FLYOUT_CLOSE_SEC;
 	end
 --]]
 end
 
 function MultiCastFlyoutFrame_OnUpdate(self, elapsed)
 --[[
 	local closeCountdownSec = self.closeCountdownSec;
 	if ( closeCountdownSec ) then
 		closeCountdownSec = closeCountdownSec - elapsed;
 		if ( closeCountdownSec <= 0 ) then
 			self.closeCountdownSec = nil;
 			self:Hide();
 		else
 			self.closeCountdownSec = closeCountdownSec;
 		end
 	end
 --]]
 end
 
 function MultiCastFlyoutFrame_Hide(self, forceHide)
 	if ( forceHide or not self:IsMouseOver() ) then
 		if ( self.parent ) then
 			if ( self.parent:IsMouseOver() ) then
 				MultiCastFlyoutFrameOpenButton_Show(MultiCastFlyoutFrameOpenButton, self.type, self.parent);
 			else
 				self.parent:UnregisterEvent("MODIFIER_STATE_CHANGED");
 			end
 		end
 		self:Hide();
 	end
 end
 
 function MultiCastFlyoutFrame_ToggleFlyout(self, type, parent)
 	if ( self:IsShown() and self.parent == parent ) then
 		MultiCastFlyoutFrame_Hide(self, true);
 	else
 		local toptcoords;
 		local midtcoords;
 		local closetcoords;
 		if ( type == "slot" ) then
 			local actionId = parent:GetID();
 			local slot = _ComputeMultiCastSlot(actionId);
 			if ( MultiCastFlyoutFrame_LoadSlotSpells(self, slot, GetMultiCastTotemSpells(actionId)) ) then
 				toptcoords = FLYOUT_TOP_TCOORDS[slot];
 				midtcoords = FLYOUT_MIDDLE_TCOORDS[slot];
 				closetcoords = FLYOUT_DOWN_BUTTON_TCOORDS[slot];
 			end
 		elseif ( type == "page" ) then
 			if ( MultiCastFlyoutFrame_LoadPageSpells(self) ) then
 				toptcoords = FLYOUT_TOP_TCOORDS["summon"];
 				midtcoords = FLYOUT_MIDDLE_TCOORDS["summon"];
 				closetcoords = FLYOUT_DOWN_BUTTON_TCOORDS["summon"];
 			end
 		end
 		if ( toptcoords ) then
 			self.type = type;
 			self.parent = parent;
 			self:SetPoint("BOTTOM", parent, "TOP", 0, 0);
 			self:Show();
 
 			self.top:SetTexCoord(toptcoords.left, toptcoords.right, toptcoords.top, toptcoords.bottom);
 			self.middle:SetTexCoord(midtcoords.left, midtcoords.right, midtcoords.top, midtcoords.bottom);
 			MultiCastFlyoutFrameCloseButton.normalTexture:SetTexCoord(closetcoords.left, closetcoords.right, closetcoords.top, closetcoords.bottom);
 		end
 	end
 end
 
 function MultiCastFlyoutFrame_LoadPageSpells(self)
 	local numKnownSpells = 0;
 	for i, spellId in next, TOTEM_MULTI_CAST_SUMMON_SPELLS do
 		if ( knownMultiCastSummonSpells[i] ) then
 			numKnownSpells = numKnownSpells + 1;
 		end
 	end
 	if ( numKnownSpells == 0 ) then
 		return false;
 	end
 
 	self.buttons = self.buttons or {};
 	local buttons = self.buttons;
 	local numButtons = #buttons;
 
 	local name = self:GetName();
 	local totalHeight = 0;
 	local button;
 	local spellId;
 	local name, rank, icon;
 	local buttonIndex = 1;
 	for i, spellId in next, TOTEM_MULTI_CAST_SUMMON_SPELLS do
 		if ( knownMultiCastSummonSpells[i] ) then
 			-- create the button
 			if ( buttonIndex <= numButtons ) then
 				button = buttons[buttonIndex];
 				if ( buttonIndex == 1 ) then
 					totalHeight = totalHeight + MULTI_CAST_FLYOUT_BUTTON_INITIAL_OFFSET;
 				else
 					totalHeight = totalHeight + MULTI_CAST_FLYOUT_BUTTON_OFFSET;
 				end
 			else
 				button = CreateFrame("Button", "MultiCastFlyoutButton"..buttonIndex, self, "MultiCastFlyoutButtonTemplate");
 				if ( buttonIndex == 1 ) then
 					-- this is the first button, anchor it to the frame
 					button:SetPoint("BOTTOM", self, "BOTTOM", 0, MULTI_CAST_FLYOUT_BUTTON_INITIAL_OFFSET);
 					totalHeight = totalHeight + MULTI_CAST_FLYOUT_BUTTON_INITIAL_OFFSET;
 				else
 					-- this is not the first button, anchor it to the previous button
 					button:SetPoint("BOTTOM", buttons[buttonIndex - 1], "TOP", 0, MULTI_CAST_FLYOUT_BUTTON_OFFSET);
 					totalHeight = totalHeight + MULTI_CAST_FLYOUT_BUTTON_OFFSET;
 				end
 			end
 			totalHeight = totalHeight + button:GetHeight();
 
 			-- setup the button
 			button.page = i;
 			spellId = TOTEM_MULTI_CAST_SUMMON_SPELLS[i];
 			button.spellId = spellId;
 			name, rank, icon = GetSpellInfo(spellId);
 			button.icon:SetTexture(icon);
 			button.icon:SetTexCoord(0.0, 1.0, 0.0, 1.0);
 
 			button:Show();
 
 			buttonIndex = buttonIndex + 1;
 		end
 	end
 	-- hide unused buttons
 	for i = buttonIndex, numButtons do
 		buttons[i]:Hide();
 	end
 
 	self:SetHeight(totalHeight + 2 + MultiCastFlyoutFrameCloseButton:GetHeight());
 
 	return true;
 end
 
 function MultiCastFlyoutFrame_LoadSlotSpells(self, slot, ...)
 	local numSpells = select("#", ...);
 	if ( numSpells == 0 ) then
 		return false;
 	end
 	-- add one to numSpells to represent the "none" slot
 	numSpells = numSpells + 1;
 
 	self.buttons = self.buttons or {};
 	local buttons = self.buttons;
 	local numButtons = #buttons;
 
 	local name = self:GetName();
 	local totalHeight = 0;
 	local button;
 	local spellId;
 	local name, rank, icon;
 	local tcoords;
 	local tcoordLeft, tcoordRight, tcoordTop, tcoordBottom;
 	for i = 1, numSpells do
 		-- create the button
 		if ( i <= numButtons ) then
 			button = buttons[i];
 			if ( i == 1 ) then
 				totalHeight = totalHeight + MULTI_CAST_FLYOUT_BUTTON_INITIAL_OFFSET;
 			else
 				totalHeight = totalHeight + MULTI_CAST_FLYOUT_BUTTON_OFFSET;
 			end
 		else
 			button = CreateFrame("Button", "MultiCastFlyoutButton"..i, self, "MultiCastFlyoutButtonTemplate");
 			button:ClearAllPoints();
 			if ( i == 1 ) then
 				-- this is the first button, anchor it to the frame
 				button:SetPoint("BOTTOM", self, "BOTTOM", 0, MULTI_CAST_FLYOUT_BUTTON_INITIAL_OFFSET);
 				totalHeight = totalHeight + MULTI_CAST_FLYOUT_BUTTON_INITIAL_OFFSET;
 			else
 				-- this is not the first button, anchor it to the previous button
 				button:SetPoint("BOTTOM", buttons[i - 1], "TOP", 0, MULTI_CAST_FLYOUT_BUTTON_OFFSET);
 				totalHeight = totalHeight + MULTI_CAST_FLYOUT_BUTTON_OFFSET;
 			end
 		end
 		totalHeight = totalHeight + button:GetHeight();
 
 		-- setup the button
 		if ( i == 1 ) then
 			-- the first button clears your slot
 			spellId = 0;
 			icon = "Interface\\Buttons\\UI-TotemBar";
 			tcoords = SLOT_EMPTY_TCOORDS[slot];
 			tcoordLeft, tcoordRight, tcoordTop, tcoordBottom = tcoords.left, tcoords.right, tcoords.top, tcoords.bottom;
 		else
 			spellId = select(i - 1, ...);
 			name, rank, icon = GetSpellInfo(spellId);
 			tcoordLeft, tcoordRight, tcoordTop, tcoordBottom = 0.0, 1.0, 0.0, 1.0;
 		end
 		button.spellId = spellId;
 		button.icon:SetTexture(icon);
 		button.icon:SetTexCoord(tcoordLeft, tcoordRight, tcoordTop, tcoordBottom);
 
 		button:Show();
 	end
 	-- hide unused buttons
 	for i = numSpells + 1, numButtons do
 		buttons[i]:Hide();
 	end
 
 	self:SetHeight(totalHeight + 2 + MultiCastFlyoutFrameCloseButton:GetHeight());
 
 	return true;
 end
 
 
 --
 -- MultiCastFlyoutFrameCloseButton
 --
 
 function MultiCastFlyoutFrameCloseButton_OnClick(self)
 	self:GetParent():Hide();
 end
 
 
 --
 -- MultiCastFlyoutFrameOpenButton
 --
 
 function MultiCastFlyoutFrameOpenButton_OnClick(self)
 	MultiCastFlyoutFrame_ToggleFlyout(MultiCastFlyoutFrame, self.type, self.parent);
 end
 
 function MultiCastFlyoutFrameOpenButton_OnLeave(self)
 	self:Hide();
 end
 
 function MultiCastFlyoutFrameOpenButton_Show(self, type, parent)
 	local tcoords;
 	if ( type == "page" ) then
 		tcoords = FLYOUT_UP_BUTTON_TCOORDS["summon"];
 	elseif ( type == "slot" ) then
 		local slot = _ComputeMultiCastSlot(parent:GetID());
 		tcoords = FLYOUT_UP_BUTTON_TCOORDS[slot];
 	end
 	if ( tcoords ) then
 		self.normalTexture:SetTexCoord(tcoords.left, tcoords.right, tcoords.top, tcoords.bottom);
 		self.type = type;
 		self.parent = parent;
 		self:SetParent(parent);
 		self:SetPoint("BOTTOM", parent, "TOP", 0, 0);
 		self:Show();
 	end
 end
 
 function MultiCastFlyoutFrameOpenButton_Hide(self, force)
 	if ( force or (not self:IsMouseOver() and not self.parent:IsMouseOver()) ) then
 		self.type = nil;
 		self:Hide();
 	end
 end
 
 
 --
 -- MultiCastSpellButton
 --
 
 function MultiCastSpellButton_OnLoad(self)
 	self:RegisterForClicks("AnyUp");
 
 	local name = self:GetName();
 	local normalTexture = _G[name.."NormalTexture"];
 	normalTexture:SetWidth(50);
 	normalTexture:SetHeight(50);
 end
 
 function MultiCastSpellButton_OnEvent(self, event, ...)
 	if ( event == "UPDATE_BINDINGS" ) then
 		ActionButton_UpdateHotkeys(self, self.buttonType);
 	elseif ( event == "ACTIONBAR_UPDATE_COOLDOWN" ) then
 		MultiCastSpellButton_UpdateCooldown(self);
 	elseif ( event == "ACTIONBAR_UPDATE_STATE" ) then
 		MultiCastSpellButton_UpdateState(self);
 	end
 end
 
 function MultiCastSpellButton_OnEnter(self)
 	MultiCastSpellButton_SetTooltip(self);
 end
 
 function MultiCastSpellButton_OnLeave(self)
 	GameTooltip:Hide();
 end
 
 function MultiCastSpellButton_SetTooltip(self)
 	if ( GetCVarBool("UberTooltips") ) then
 		GameTooltip_SetDefaultAnchor(GameTooltip, self);
 	else
 		GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
 	end
 	if ( GameTooltip:SetSpellByID(self.spellId, false, true) ) then
 		self.UpdateTooltip = MultiCastSpellButton_SetTooltip;
 	else
 		self.UpdateTooltip = nil;
 	end
 end
 
 function MultiCastSpellButton_UpdateCooldown(self)
 	local cooldown = _G[self:GetName().."Cooldown"];
 	local start, duration, enable = GetSpellCooldown(self.spellId);
 	CooldownFrame_SetTimer(cooldown, start, duration, enable);
 end
 
 function MultiCastSpellButton_UpdateState(self)
 	if ( IsCurrentSpell(self.spellId) ) then
-		self:SetChecked(1);
+		self:SetChecked(true);
 	else
-		self:SetChecked(nil);
+		self:SetChecked(false);
 	end
 end
 
 
 --
 -- MultiCastSummonSpellButton
 --
 
 function MultiCastSummonSpellButton_OnLoad(self)
 	self.buttonType = "MULTICASTSUMMONBUTTON";
 	MultiCastSpellButton_OnLoad(self);
 end
 
 function MultiCastSummonSpellButton_OnEvent(self, event, ...)
 	MultiCastSpellButton_OnEvent(self, event, ...);
 --[[
 	if ( event == "MODIFIER_STATE_CHANGED" ) then
 		if ( IsModifiedClick("SHOWMULTICASTFLYOUT") and self:IsMouseOver() ) then
 			MultiCastSummonSpellButton_OnEnter(self);
 		end
 	end
 --]]
 end
 
 function MultiCastSummonSpellButton_OnClick(self)
 	MultiCastSummonSpellButtonUp(self:GetID());
 end
 
 function MultiCastSummonSpellButton_OnEnter(self)
 	MultiCastSpellButton_OnEnter(self);
 
 	if ( MultiCastFlyoutFrame.parent ~= self ) then
 		MultiCastFlyoutFrameOpenButton_Show(MultiCastFlyoutFrameOpenButton, "page", self);
 	end
 --[[
 	self:RegisterEvent("MODIFIER_STATE_CHANGED");
 	if ( IsModifiedClick("SHOWMULTICASTFLYOUT") ) then
 		MultiCastFlyoutFrame_ToggleFlyout(MultiCastFlyoutFrame, "page", self);
 	end
 --]]
 end
 
 function MultiCastSummonSpellButton_OnLeave(self)
 	MultiCastSpellButton_OnLeave(self);
 	MultiCastFlyoutFrameOpenButton_Hide(MultiCastFlyoutFrameOpenButton);
 end
 
 function MultiCastSummonSpellButton_Update(self)
 	-- first update which multi-cast spells we actually know
 	for index, spellId in next, TOTEM_MULTI_CAST_SUMMON_SPELLS do
 		knownMultiCastSummonSpells[index] = (IsSpellKnown(spellId) and spellId) or nil;
 	end
 
 	-- update the spell button
 	local spellId = knownMultiCastSummonSpells[self:GetID()];
 	self.spellId = spellId;
 	if ( HasMultiCastActionBar() and spellId ) then
 		local name, rank, icon, cost, isFunnel, powerType, castTime, minRage, maxRange = GetSpellInfo(spellId);
 		local buttonName = self:GetName();
 		_G[buttonName.."Icon"]:SetTexture(icon);
 
 		if ( not self.eventsRegistered ) then
 			self:RegisterEvent("UPDATE_BINDINGS");
 			self:RegisterEvent("ACTIONBAR_UPDATE_STATE");
 			self:RegisterEvent("ACTIONBAR_UPDATE_COOLDOWN");
 			self.eventsRegistered = true;
 		end
 		ActionButton_UpdateHotkeys(self, self.buttonType);
 		MultiCastSpellButton_UpdateCooldown(self);
 
 		if ( GameTooltip:GetOwner() == self ) then
 			MultiCastSpellButton_SetTooltip(self);
 		end
 
 		-- reanchor the first slot button take make room for this button
 		local width = self:GetWidth();
 		local xOffset = width + 8 + 3;
 		local page;
 		for i = 1, NUM_MULTI_CAST_PAGES do
 			page = _G["MultiCastActionPage"..i];
 			page:SetPoint("BOTTOMLEFT", page:GetParent(), "BOTTOMLEFT", xOffset, 3);
 		end
 		MultiCastSlotButton1:SetPoint("BOTTOMLEFT", self:GetParent(), "BOTTOMLEFT", xOffset, 3);
 
 		self:Show();
 	else
 		if ( self.eventsRegistered ) then
 			self:UnregisterEvent("UPDATE_BINDINGS");
 			self:UnregisterEvent("ACTIONBAR_UPDATE_STATE");
 			self:UnregisterEvent("ACTIONBAR_UPDATE_COOLDOWN");
 			self.eventsRegistered = false;
 		end
 
 		-- reanchor the first slot button take the place of this button
 		local xOffset = 3;
 		local page;
 		for i = 1, NUM_MULTI_CAST_PAGES do
 			page = _G["MultiCastActionPage"..i];
 			page:SetPoint("BOTTOMLEFT", page:GetParent(), "BOTTOMLEFT", xOffset, 3);
 		end
 		MultiCastSlotButton1:SetPoint("BOTTOMLEFT", self:GetParent(), "BOTTOMLEFT", xOffset, 3);
 
 		self:Hide();
 	end
 end
 
 function MultiCastSummonSpellButtonUp(id)
 	CastSpellByID(TOTEM_MULTI_CAST_SUMMON_SPELLS[id]);
 end
 
 
 --
 -- MultiCastRecallSpellButton
 --
 
 function MultiCastRecallSpellButton_OnLoad(self)
 	self.buttonType = "MULTICASTRECALLBUTTON";
 	MultiCastSpellButton_OnLoad(self);
 end
 
 function MultiCastRecallSpellButton_OnClick(self)
 	MultiCastRecallSpellButtonUp(self:GetID());
 end
 
 function MultiCastRecallSpellButton_Update(self)
 	-- first update which multi-cast spells we actually know
 	for index, spellId in next, TOTEM_MULTI_CAST_RECALL_SPELLS do
 		knownMultiCastRecallSpells[index] = (IsSpellKnown(spellId) and spellId) or nil;
 	end
 
 	-- update the spell button
 	local spellId = knownMultiCastRecallSpells[self:GetID()];
 	self.spellId = spellId;
 	if ( HasMultiCastActionBar() and spellId ) then
 		local name, rank, icon, cost, isFunnel, powerType, castTime, minRage, maxRange = GetSpellInfo(spellId);
 		local buttonName = self:GetName();
 		_G[buttonName.."Icon"]:SetTexture(icon);
 
 		if ( not self.eventsRegistered ) then
 			self:RegisterEvent("UPDATE_BINDINGS");
 			self:RegisterEvent("ACTIONBAR_UPDATE_STATE");
 			self:RegisterEvent("ACTIONBAR_UPDATE_COOLDOWN");
 			self.eventsRegistered = true;
 		end
 		ActionButton_UpdateHotkeys(self, self.buttonType);
 		MultiCastSpellButton_UpdateCooldown(self);
 
 		if ( GameTooltip:GetOwner() == self ) then
 			MultiCastSpellButton_SetTooltip(self);
 		end
 
 		-- anchor to the last shown slot
 		local activeSlots = MultiCastActionBarFrame.numActiveSlots;
 		if ( activeSlots > 0 ) then
 			self:SetPoint("LEFT", _G["MultiCastSlotButton"..activeSlots], "RIGHT", 8, 0);
 		end
 
 		self:Show();
 	else
 		if ( self.eventsRegistered ) then
 			self:UnregisterEvent("UPDATE_BINDINGS");
 			self:UnregisterEvent("ACTIONBAR_UPDATE_STATE");
 			self:UnregisterEvent("ACTIONBAR_UPDATE_COOLDOWN");
 			self.eventsRegistered = false;
 		end
 
 		self:Hide();
 	end
 end
 
 function MultiCastRecallSpellButtonUp(id)
 	CastSpellByID(TOTEM_MULTI_CAST_RECALL_SPELLS[id]);
 end