--------------------------------------------------------------------------
-- MobileFrames.lua 
--------------------------------------------------------------------------
--[[
Mobile Frames

By: AnduinLothar    <KarlKFI@cosmosui.org>
		
	$Id: MobileFrames.lua 4365 2006-12-05 15:52:08Z legorol $
	$Rev: 4365 $
	$LastChangedBy: legorol $
	$Date: 2006-12-05 09:52:08 -0600 (Tue, 05 Dec 2006) $


]]--

MobileFrames_AnchorsSoundOn = true;

MobileFrames_UIPanelWindowBackup = {};
MobileFrames_UIPanelsVisible = {};
MobileFrames_RightSide_IsReset = {};
MobileFrames_MasterEnableList = {};
MobileFrames_MasterAnchorEnableList = {};
MobileFrames_MinimapButtonDefaultCoords = {};
MobileFrames_ResetFrame = {};			--reset a mobile frame using MobileFrames_ResetFrame[frameName]() used for cosmos config
MobileFrames_EnableToggle = {};			--enable/disable a mobile frame using MobileFrames_EnableToggle[frameName](1/0) used for cosmos config
MobileFrames_EnabledByDefault = true;   --true or false, never use nil
local SavedCloseWindows = nil;
MobileFrames_RollStackDown = nil;
MobileFrames_Tooltip_Enabled = true;
UIPANEL_OFFSET_LEFT = 0;

MOBILEFRAMES_CONTAINER_POINT = "Point";
MOBILEFRAMES_CONTAINER_RELATIVETO = "RelativeTo";
MOBILEFRAMES_CONTAINER_RELATIVEPOINT = "RelativePoint";
MOBILEFRAMES_CONTAINER_POSITION = "Position";

MobileFrames_ContainerPointSettings = {
	[MOBILEFRAMES_CONTAINER_POINT] = "TOPLEFT",
	[MOBILEFRAMES_CONTAINER_RELATIVETO] = "UIParent",
	[MOBILEFRAMES_CONTAINER_RELATIVEPOINT] = "BOTTOMLEFT",
	--[MOBILEFRAMES_CONTAINER_POSITION] = nil
};

MobileFrames_SpecialFrames = { };

function MobileFrames_DefineSpecialFrames()
	MobileFrames_SpecialFrames = {

		PlayerFrame = { default = MobileFrames_EnabledByDefault, func = function(checked) MobileFrames_AnchorToggleEnableGeneral("PlayerFrame", checked) end, reset = MobileFrames_ResetMobilePlayerFrame },
		PetFrame = { default = MobileFrames_EnabledByDefault, func = function(checked) MobileFrames_AnchorToggleEnableGeneral("PetFrame", checked) end, reset = MobileFrames_ResetMobilePetFrame },
		TargetFrame = { default = MobileFrames_EnabledByDefault, func = function(checked) MobileFrames_AnchorToggleEnableGeneral("TargetFrame", checked) end, reset = MobileFrames_ResetMobileTargetFrame },
		TargetofTargetFrame = { default = MobileFrames_EnabledByDefault, func = function(checked) MobileFrames_AnchorToggleEnableGeneral("TargetofTargetFrame", checked) end, reset = MobileFrames_ResetMobileTargetofTargetFrame },
		PartyMemberFrames = { default = MobileFrames_EnabledByDefault, func = MobileFrames_EnableMobilePartyMemberFrames, reset = MobileFrames_ResetMobilePartyMemberFrames},
		Containers = { default = MobileFrames_EnabledByDefault, func = MobileFrames_EnableMobileContainers, reset = MobileFrames_ResetMobileContainers},
		BottomMultiBars = { reset = MobileFrames_ResetMobileBottomMultiBars, default = MobileFrames_EnabledByDefault, func = MobileFrames_EnableMobileBottomMultiBars },
		SideMultiBars = { reset = MobileFrames_ResetMobileSideMultiBars, default = MobileFrames_EnabledByDefault, func = MobileFrames_EnableMobileSideMultiBars },
		MinimapCluster = { reset = MobileFrames_ResetMobileMinimapCluster, default = MobileFrames_EnabledByDefault, func = function(checked) MobileFrames_AnchorToggleEnableGeneral("MinimapCluster", checked) end },
		QuestWatchFrame = { reset = function() MobileFrames_UIParent_ManageRightSideFrames(true, nil) end, default = MobileFrames_EnabledByDefault, func = function(checked) MobileFrames_ToggleEnableGeneral("QuestWatchFrame", checked) end },
		FramerateLabel = { reset = MobileFrames_FramerateLabelReset, default = MobileFrames_EnabledByDefault, func = function(checked) MobileFrames_ToggleEnableGeneral("FramerateLabel", checked) end },
		DurabilityFrame = { reset = function() MobileFrames_UIParent_ManageRightSideFrames(nil, true) end, default = MobileFrames_EnabledByDefault, func = function(checked) MobileFrames_ToggleEnableGeneral("DurabilityFrame", checked) end },
		QuestTimerFrame = { reset = function() MobileFrames_UIParent_ManageRightSideFrames(nil, nil, nil, true) end, default = MobileFrames_EnabledByDefault, func = function(checked) MobileFrames_ToggleEnableGeneral("QuestTimerFrame", checked) end },
		TicketStatusFrame = { reset = MobileFrames_ResetMobileTicketStatusFrame, default = MobileFrames_EnabledByDefault, func = function(checked) MobileFrames_AnchorToggleEnableGeneral("TicketStatusFrame", checked) end },
		TemporaryEnchantFrame = { reset = MobileFrames_ResetMobileBuffFrame, default = MobileFrames_EnabledByDefault, func = function(checked) MobileFrames_AnchorToggleEnableGeneral("TemporaryEnchantFrame", checked) end },
		WorldStateScoreFrame = { reset = MobileFrames_ResetMobileWorldStateScoreFrame, default = MobileFrames_EnabledByDefault, func = function(checked) MobileFrames_ToggleEnableGeneral("WorldStateScoreFrame", checked) end },
		WorldStateAlwaysUpFrame = { reset = MobileFrames_WorldStateAlwaysUpFrameReset, default = MobileFrames_EnabledByDefault, func = function(checked) MobileFrames_AnchorToggleEnableGeneral("WorldStateAlwaysUpFrame", checked) end },
		GroupLootFrame = { reset = function() MobileFrames_UIParent_ManageRightSideFrames(nil, nil, true) end, default = MobileFrames_EnabledByDefault, func = function(checked) MobileFrames_ToggleEnableGeneral("GroupLootFrame1", checked) end },
		CastingBarFrame = { reset = MobileFrames_CastingBarFrame_Reset, default = MobileFrames_EnabledByDefault, func = function(checked) MobileFrames_ToggleEnableGeneral("CastingBarFrame", checked) end },
		MainMenuBar = { reset = MobileFrames_MobileMainMenuBar_Reset, default = MobileFrames_EnabledByDefault, func = function(checked) MobileFrames_AnchorToggleEnableGeneral("MainMenuBar", checked) end },
		BackpackButtons = { reset = MobileFrames_MobileMainBackpackButtons_Reset, default = MobileFrames_EnabledByDefault, func = function(checked) MobileFrames_AnchorToggleEnableGeneral("MainMenuBarBackpackButton", checked) end },
		MicroButtons = { reset = MobileFrames_MobileCharacterMicroButtons_Reset, default = MobileFrames_EnabledByDefault, func = function(checked) MobileFrames_AnchorToggleEnableGeneral("CharacterMicroButton", checked) end },
		ActionButtons = { reset = MobileFrames_MobileActionButtons_Reset, default = MobileFrames_EnabledByDefault, func = function(checked) MobileFrames_AnchorToggleEnableGeneral("ActionButton1", checked) end },
		ShapeshiftBarFrame = { reset = MobileFrames_MobileShapeshiftBarFrame_Reset, default = MobileFrames_EnabledByDefault, func = function(checked) MobileFrames_AnchorToggleEnableGeneral("ShapeshiftBarFrame", checked) end },
		PetActionBarFrame = { reset = MobileFrames_MobilePetActionBarFrame_Reset, default = MobileFrames_EnabledByDefault, func = function(checked) MobileFrames_AnchorToggleEnableGeneral("PetActionBarFrame", checked) end },
		UIErrorsFrame = { reset = MobileFrames_ResetMobileUIErrorsFrame, default = MobileFrames_EnabledByDefault, func = function(checked) MobileFrames_AnchorToggleEnableGeneral("UIErrorsFrame", checked) end },
	};
end

MobileFrames_AddonFrames = {
	Blizzard_AuctionUI		= { ["AuctionFrame"] =  "AuctionFrameMobileBar" };
	--Blizzard_BindingUI		= { ["KeyBindingFrame"] = "KeyBindingFrameMobileBar" };
	Blizzard_CraftUI		= { ["CraftFrame"] = "CraftFrameMobileBar" };
	Blizzard_InspectUI		= { ["InspectFrame"] = "InspectFrameMobileBar" };
	Blizzard_MacroUI		= { ["MacroFrame"] = "MacroFrameMobileBar" };
	Blizzard_TalentUI		= { ["TalentFrame"] = "TalentFrameMobileBar" };
	Blizzard_TradeSkillUI	= { ["TradeSkillFrame"] = "TradeSkillFrameMobileBar" };
	Blizzard_TrainerUI		= { ["ClassTrainerFrame"] = "ClassTrainerFrameMobileBar" };
};

MobileFrames_MultiSpecialFrames = {
	MultiBarLeft = "SideMultiBars";
	MultiBarRight = "SideMultiBars";
	MultiBarBottomLeft = "BottomMultiBars";
	MultiBarBottomRight = "BottomMultiBars";
	PartyMemberFrame1 = "PartyMemberFrames";
	PartyMemberFrame2 = "PartyMemberFrames";
	PartyMemberFrame3 = "PartyMemberFrames";
	PartyMemberFrame4 = "PartyMemberFrames";
	ActionButton1 = "ActionButtons";
	CharacterMicroButton = "MicroButtons";
	MainMenuBarBackpackButton = "BackpackButtons";
	FramerateLabelMobileBar = "FramerateLabel";
	ContainerFrame1 = "Containers";
	ContainerFrame2 = "Containers";
	ContainerFrame3 = "Containers";
	ContainerFrame4 = "Containers";
	ContainerFrame5 = "Containers";
	ContainerFrame6 = "Containers";
	ContainerFrame7 = "Containers";
	ContainerFrame8 = "Containers";
	ContainerFrame9 = "Containers";
	ContainerFrame10 = "Containers";
	ContainerFrame11 = "Containers";
	ContainerFrame12 = "Containers";
	ContainerFrame13 = "Containers";
	ContainerFrame14 = "Containers";
	ContainerFrame15 = "Containers";
	ContainerFrame16 = "Containers";
	ContainerFrame17 = "Containers";
	GroupLootFrame1 = "GroupLootFrame";
};


function MobileFrames_OnLoad()
	
	--this:RegisterEvent("ADDON_LOADED");
	this:RegisterEvent("VARIABLES_LOADED");
	
	SlashCmdList["MOBILEFRAMES"] = MobileFrames_SlashCommandHandler;
	
	--manual hook for returning
	if (CloseWindows ~= SavedCloseWindows) then
        SavedCloseWindows = CloseWindows;
        CloseWindows = MobileFrames_CloseWindows;
    end
	
	Sea.util.hook( "ShowUIPanel", "MobileFrames_ShowUIPanel", "replace" );
	Sea.util.hook( "updateContainerFrameAnchors", "MobileFrames_updateContainerFrameAnchors", "replace" );
	Sea.util.hook( "PetActionBar_UpdatePosition", "MobileFrames_PetActionBar_UpdatePosition", "replace" );
	--Sea.util.hook( "PetActionBarFrame_OnUpdate", "MobileFrames_PetActionBarFrame_OnUpdate", "replace" );
	Sea.util.hook( "ShapeshiftBar_UpdatePosition", "MobileFrames_ShapeshiftBar_UpdatePosition", "replace" );
	
	Sea.util.hook( "UIParent_ManageFramePositions", "MobileFrames_UIParent_ManageFramePositions_before", "before" );
	Sea.util.hook( "UIParent_ManageFramePositions", "MobileFrames_UIParent_ManageFramePositions_after", "after" );
	
	Sea.util.hook( "UIParent_ManageRightSideFrames", "MobileFrames_UIParent_ManageRightSideFrames", "replace" );
	Sea.util.hook( "TicketStatusFrame_OnEvent", "MobileFrames_TicketStatusFrame_OnEvent", "replace" );
	--Sea.util.hook( "CastingBarFrame_UpdatePosition", "MobileFrames_CastingBarFrame_UpdatePosition", "replace" );
	Sea.util.hook( "ToggleFramerate", "MobileFrames_ToggleFramerateMobileBar", "after" );
	
	Sea.util.hook("SetDoublewideFrame", "MobileFrames_SetDoublewideFrame", "replace");
	Sea.util.hook("SetLeftFrame", "MobileFrames_SetLeftFrame", "replace");
	Sea.util.hook("SetCenterFrame", "MobileFrames_SetCenterFrame", "replace");
	Sea.util.hook("MovePanelToLeft", "MobileFrames_MovePanelToLeft", "replace");
	Sea.util.hook("MovePanelToCenter", "MobileFrames_MovePanelToCenter", "replace");
	
	MobileFrames_DefineSpecialFrames();
	MobileFrames_UIParent_ManageRightSideFrames(true);

end

function MobileFrames_BarOnLoad(barFrame)
	MobileFrames_UIPanel_AddFrameRepositionIgnore(barFrame:GetParent():GetName());
	MobileFrames_OverlayOnLoad(barFrame)
	--set to parent width
	barFrame:SetWidth(barFrame:GetParent():GetWidth());
	--subtract HitRectInsets/AbsInset/right value of parent stored in bar id
	--only needed since there's no GetRightHitRectInset()
	local widthOffeset = barFrame:GetID();
	if ( widthOffeset ) then
		barFrame:SetWidth(barFrame:GetWidth()-widthOffeset);
	end
end

function MobileFrames_OverlayOnLoad(barFrame)
	MobileFrames_MakeParentMobile(barFrame);
	MobileFrames_SetEnabledStatus(barFrame:GetParent());
end

function MobileFrames_SetEnabledStatus(frame)
	MobileFrames_MasterEnableList[frame:GetName()] = MobileFrames_EnabledByDefault;
end

function MobileFrames_MakeParentMobile(barFrame)
	if (not barFrame:GetParent():IsMovable()) then
		barFrame:GetParent():SetMovable(1);
	end
end

function MobileFrames_BarOnShow(barFrame)
	if MobileFrames_MasterEnableList[barFrame:GetParent():GetName()] then
		MobileFrames_AddToVisibleList(barFrame:GetParent():GetName());
	end
end

function MobileFrames_ShowTooltip(barFrame, frameName)
	if (MobileFrames_Tooltip_Enabled) then
		MobileFramesTooltip:SetOwner(barFrame, "ANCHOR_CURSOR");
		MobileFramesTooltip:SetText(format(MOBILE_FRAMES_TOOLTIP_TEXT, GetReadableFrameName(frameName)));
	end
end

function MobileFrames_HideTooltip(barFrame)
	MobileFramesTooltip:Hide();
end

function MobileFrames_BarOnEnter(barFrame)
	MobileFrames_ShowTooltip(barFrame, barFrame:GetParent():GetName());
end

function MobileFrames_BarOnLeave(barFrame)
	MobileFrames_HideTooltip(barFrame);
end

function MobileFrames_BarOnMouseUp(barFrame)
	MobileFrames_BarStopDrag(barFrame);
end

function MobileFrames_BarOnMouseDown(barFrame)
	if (arg1 == "RightButton") and (IsShiftKeyDown()) then
		MobileFramesDropDown.displayMode = "MENU";
		ToggleDropDownMenu(1, barFrame:GetParent():GetName(), MobileFramesDropDown, barFrame:GetName());
	else
		MobileFrames_BarStartDrag(barFrame);
	end
end

function MobileFrames_BarOnHide(barFrame)
	MobileFrames_BarStopDrag(barFrame);
	MobileFrames_RemoveFromVisibleList(barFrame:GetParent():GetName());
end

function MobileFrames_BarStopDrag(barFrame)
	MobileFrames_StopDrag(barFrame:GetParent());
end

function MobileFrames_StopDrag(frame)
	if ( frame.isMoving ) then
		frame:StopMovingOrSizing();
		frame.isMoving = false;
	end
end

function MobileFrames_BarStartDrag(barFrame)
	MobileFrames_StartDrag(barFrame:GetParent());
end

function MobileFrames_StartDrag(frame)
	if ( ( ( not frame.isLocked ) or ( frame.isLocked == 0 ) ) and ( arg1 == "LeftButton" ) ) then
		frame:StartMoving();
		frame.isMoving = true;
		frame.isReset = nil;
	end
end

function MobileFrames_BarOnDragStart(barFrame)
	MobileFrames_OnDragStart(barFrame:GetParent())
end

function MobileFrames_OnDragStart(frame)
	if frame.isMoving then
		frame:StopMovingOrSizing();
		frame.isMoving = false;
	end
	MobileFrames_RemoveFromVisibleList(frame:GetName());
end

function MobileFrames_SortByReadableFrameName(a,b) 
	return (GetReadableFrameName(a) < GetReadableFrameName(b));
end

function MobileFrames_SetPoint_Hook(self, point, relativeFrame, relativePoint ,xOfs ,yOfs)
	local frameName = self:GetName();
	if (self:IsUserPlaced()) then
		if (MobileFrames_MasterEnableList[frameName]) then
			return;
		elseif (MobileFrames_MasterAnchorEnableList[frameName]) then
			return;
		end
	end
	return true;
end

function MobileFrames_FramerateLabel_SetPoint_Hook(self, point, relativeFrame, relativePoint ,xOfs ,yOfs)
	local frameName = self:GetName();
	if (FramerateLabelMobileBar:IsUserPlaced()) then
		if (MobileFrames_MasterEnableList[frameName]) then
			return;
		end
	end
	FramerateLabelMobileBar:SetPoint(point, relativeFrame, relativePoint ,xOfs ,yOfs);
end

function MobileFrames_OnEvent(event)
	if (event == "ADDON_LOADED") then
		local frames = MobileFrames_AddonFrames[arg1];
		if (frames) then
			for frameName, mobileFrameName in pairs(frames) do
				getglobal(mobileFrameName):SetParent(frameName);
			end
		end
	elseif (event == "VARIABLES_LOADED") then
		if (PopNUI_UIParent_ManageRightSideFrames) then
			Sea.util.unhook("UIParent_ManageRightSideFrames", "PopNUI_UIParent_ManageRightSideFrames", "after");
		end
		if (Eclipse) then
			if (Eclipse.UIParent_ManageRightSideFrames) then
				Sea.util.unhook("UIParent_ManageRightSideFrames", "Eclipse.UIParent_ManageRightSideFrames", "after");
			end
			if (Eclipse.ShapeshiftBar_UpdatePosition) then
				Sea.util.unhook("ShapeshiftBar_UpdatePosition", "Eclipse.ShapeshiftBar_UpdatePosition", "replace");
			end
			if (Eclipse.PetActionBar_UpdatePosition) then
				Sea.util.unhook("PetActionBar_UpdatePosition", "Eclipse.PetActionBar_UpdatePosition", "after");
			end
		end
		
		--define enable/disable functions for all loaded frames
		table.foreach(MobileFrames_MasterEnableList, function(frameName) MobileFrames_EnableToggle[frameName] = function(checked) MobileFrames_ToggleEnableGeneral(frameName, checked); end; end);
		--define reset functions for all loaded frames
		table.foreach(MobileFrames_MasterEnableList, function(frameName) MobileFrames_ResetFrame[frameName] = function() MobileFrames_Reset(frameName); end; end);
		
		for frameName,v in pairs(MobileFrames_MasterEnableList) do
			if (getglobal(frameName).IsUserPlaced) then
				Sea.util.hook(frameName..".SetPoint", "MobileFrames_SetPoint_Hook", "replace");
			elseif (frameName == "FramerateLabel") then
				Sea.util.hook(frameName..".SetPoint", "MobileFrames_FramerateLabel_SetPoint_Hook", "replace");
			end
		end
		
		for frameName,v in pairs(MobileFrames_MasterAnchorEnableList) do
			if (getglobal(frameName).IsUserPlaced) then
				Sea.util.hook(frameName..".SetPoint", "MobileFrames_SetPoint_Hook", "replace");
			end
		end
		
		if (not MobileFrames_ContainerPositionsByID) then
			MobileFrames_ContainerPositionsByID = {};
		end
		
		--Update Bar Graphics
		UIParent_ManageFramePositions();
		
		if (COS_MOBILE_FRAMES_CONTAINERS_X) then
			MobileFrames_MobileContainers = (COS_MOBILE_FRAMES_CONTAINERS_X == 1);
		else
			if (MobileFrames_MobileContainers == nil) then
				MobileFrames_MobileContainers = MobileFrames_EnabledByDefault;
			end
		end
		
		if (MobileFrames_SavedEnableList) then
			--use saved enable states
			for frameName, enabled in pairs(MobileFrames_SavedEnableList) do
				if MobileFrames_MasterEnableList[frameName] ~= nil then
					--mobile frame was loaded and has a saved value, use it
					MobileFrames_MasterEnableList[frameName] = enabled;
				end
			end
		end
		
		--this and the previous if arn't mutually exclusive (Ex: had MFs and just added khaos)
		if ( Khaos ) then 
			MobileFrames_RegisterForKhaos();
		else
			--restore saved enable states
			local checked;
			if (MobileFrames_SavedEnableList) then
				for frameName, enabled in pairs(MobileFrames_SavedEnableList) do
					if (enabled) then
						checked = 1;
					else
						checked = 0;
					end
					if (type(MobileFrames_SpecialFrames[frameName]) == "table") then
						MobileFrames_SpecialFrames[frameName].func(checked);
						--MobileFrames_Print(frameName.." enable set to "..checked);
					elseif (MobileFrames_MasterEnableList[frameName] ~= nil) then
						MobileFrames_EnableToggle[frameName](checked);
						--MobileFrames_Print(frameName.." enable set to "..checked);
					end
				end
			end
			if (MobileFrames_SavedAnchorEnableList) then
				for frameName, enabled in pairs(MobileFrames_SavedAnchorEnableList) do
					if (enabled) then
						checked = 1;
					else
						checked = 0;
					end
					if (type(MobileFrames_SpecialFrames[frameName]) == "table") then
						MobileFrames_SpecialFrames[frameName].func(checked);
						--MobileFrames_Print(frameName.." enable set to "..checked);
					elseif (type(MobileFrames_SpecialFrames[MobileFrames_MultiSpecialFrames[frameName]]) == "table") then
						MobileFrames_SpecialFrames[MobileFrames_MultiSpecialFrames[frameName]].func(checked);
						--MobileFrames_Print(MobileFrames_MultiSpecialFrames[frameName].." enable set to "..checked);
					end
				end
			end
			MobileFrames_SavedEnableList = MobileFrames_MasterEnableList;
			MobileFrames_SavedAnchorEnableList = MobileFrames_MasterAnchorEnableList;
			if (MobileFrames_MobileContainers ~= nil) then
				if (MobileFrames_MobileContainers) then
					checked = 1;
				else
					checked = 0;
				end
				MobileFrames_EnableMobileContainers(checked);
				--MobileFrames_Print("Bags enable set to "..checked);
			end
			if (MobileFrames_RollStackDown) then
				MobileFrames_SetDownwardRollWindowStack(1);
			end
		end
		
		if (EarthFeature_AddButton) then 
			EarthFeature_AddButton(
				{
					id="ToggleMobileAnchors";
					name=TEXT(MOBILE_FRAMES_TOGGLEANCHORS);
					tooltip=TEXT(MOBILE_FRAMES_TOGGLEANCHORS_INFO);
					icon="Interface\\AddOns\\MobileFrames\\Skin\\Anchor";
					callback=MobileFrames_ToggleAnchors;
				}
			);
		end
	
	end
end


function MobileFrames_RegisterForKhaos()
	local optionSet = {
		id="MobileFrames";
		text=MOBILE_FRAMES_HEADER;
		helptext=MOBILE_FRAMES_HEADER_INFO;
		difficulty=1;
		options={
			{
				id="Header";
				text=MOBILE_FRAMES_HEADER;
				helptext=MOBILE_FRAMES_HEADER_INFO;
				type=K_HEADER;
				difficulty=1;
			};
			{
				id="EnableAll";
				type=K_BUTTON;
				text=MOBILE_FRAMES_ENABLE_ALL_TEXT;
				helptext=MOBILE_FRAMES_ENABLE_ALL_TEXT_INFO;
				callback=function()MobileFrames_Enable("")end;
				setup={buttonText=ENABLE_ALL};
			};
			{
				id="DisableAll";
				type=K_BUTTON;
				text=MOBILE_FRAMES_DISABLE_ALL_TEXT;
				helptext=MOBILE_FRAMES_DISABLE_ALL_TEXT_INFO;
				callback=function()MobileFrames_Disable("")end;
				setup={buttonText=DISABLE_ALL};
			};
			{
				id="ResetAll";
				type=K_BUTTON;
				text=MOBILE_FRAMES_RESET_ALL_TEXT;
				helptext=MOBILE_FRAMES_RESET_ALL_TEXT_INFO;
				callback=function()MobileFrames_Reset("")end;
				setup={buttonText=RESET_ALL};
			};
			{
				id="ToggleAnchors";
				type=K_BUTTON;
				text=MOBILE_FRAMES_TOGGLEANCHORS;
				helptext=MOBILE_FRAMES_TOGGLEANCHORS_INFO;
				callback=MobileFrames_ToggleAnchors;
				setup={buttonText=MOBILE_FRAMES_TOGGLEANCHORS};
			};
			{
				id="EnableSound";
				type=K_TEXT;
				text=MOBILE_FRAMES_ENABLE_SOUND;
				helptext=MOBILE_FRAMES_ENABLE_SOUND_INFO;
				callback=function(state)MobileFrames_AnchorsSoundOn=state.checked; end;
				feedback=function(state)
					if ( state.checked ) then 
						return MOBILE_FRAMES_SOUND_FEEDBACK_ENABLED;
					else
						return MOBILE_FRAMES_SOUND_FEEDBACK_DISABLED;
					end;
				end;
				check=true;
				default={checked=true};
				disabled={checked=false};
			};
			{
				id="DownwardsRollWindowStacking";
				type=K_TEXT;
				text=MOBILE_FRAMES_DOWN_ROLLSTACK;
				helptext=MOBILE_FRAMES_DOWN_ROLLSTACK_INFO;
				callback=function(state)
					if ( state.checked ) then
						MobileFrames_SetDownwardRollWindowStack(1);
					else
						MobileFrames_SetDownwardRollWindowStack(0);
					end
				end;
				feedback=function(state)
					if ( state.checked ) then 
						return MOBILE_FRAMES_ROLLSTACK_FEEDBACK_ENABLED;
					else
						return MOBILE_FRAMES_ROLLSTACK_FEEDBACK_DISABLED;
					end;
				end;
				check=true;
				default={checked=false};
				disabled={checked=false};
			};
			{
				id="SetContainerOffset";
				type=K_SLIDER;
				text=MOBILE_FRAMES_SET_CONTAINERS_OFFSET;
				helptext=MOBILE_FRAMES_SET_CONTAINERS_OFFSET_INFO;
				callback=function(state)
					if ( state.checked ) then 
						MobileFrames_SetContainerOffset(1,state.slider);
					else
						MobileFrames_SetContainerOffset();
					end
				end;
				feedback=function(state)
					if ( state.checked ) then 
						MobileFrames_ContainerOffsetMarker_Show();
						return format(MOBILE_FRAMES_CONTAINERS_OFFSET_FEEDBACK_ENABLED, state.slider);
					else
						return MOBILE_FRAMES_CONTAINERS_OFFSET_FEEDBACK_DISABLED;
					end;
				end;
				check=true;
				default={checked=false;slider=CONTAINER_OFFSET_X};
				disabled={checked=false;slider=CONTAINER_OFFSET_X};
				dependencies={SetContainerOffset={checked=true;match=true}};
				setup={
					sliderStep=5;
					sliderText=OFFSET;
					sliderMin=0;
					sliderMax=200;
				};
			};
			{
				id="SetUIPanelOffset";
				type=K_SLIDER;
				text=MOBILE_FRAMES_SET_UIPANEL_OFFSET;
				helptext=MOBILE_FRAMES_SET_UIPANEL_OFFSET_INFO;
				callback=function(state)
					if ( state.checked ) then 
						MobileFrames_SetUIPanelOffsetLeft(1,state.slider);
					else
						MobileFrames_SetUIPanelOffsetLeft(0,state.slider);
					end
				end;
				feedback=function(state)
					if ( state.checked ) then 
						MobileFrames_UIPanelOffsetMarker_Show();
						return format(MOBILE_FRAMES_UIPANEL_OFFSET_FEEDBACK_ENABLED, state.slider);
					else
						return MOBILE_FRAMES_UIPANEL_OFFSET_FEEDBACK_DISABLED;
					end;
				end;
				check=true;
				default={checked=false;slider=0};
				disabled={checked=false;slider=0};
				dependencies={SetUIPanelOffset={checked=true;match=true}};
				setup={
					sliderStep=5;
					sliderText=OFFSET;
					sliderMin=0;
					sliderMax=200;
				};
			};
			{
				id="RegularHeader";
				type=K_HEADER;
				text=MOBILE_FRAMES_REGULAR_HEADER;
				helptext=MOBILE_FRAMES_REGULAR_HEADER_INFO;
			};
		};
	};
	local alphaList = MobileFrames_GetTableKeyList(MobileFrames_MasterEnableList);
	table.sort(alphaList, MobileFrames_SortByReadableFrameName);
	for index, frameName in pairs(alphaList) do
		if (not MobileFrames_SpecialFrames[frameName]) and (not MobileFrames_MultiSpecialFrames[frameName]) then
			local frameName2 = frameName;
			local readableFrameName2 = GetReadableFrameName(frameName);
			table.insert(optionSet.options, 
				{
					id="Enable"..frameName;
					type=K_BUTTON;
					check=true;
					text=string.format(MOBILE_FRAMES_ENABLE_TEXT, readableFrameName2);
					helptext=string.format(MOBILE_FRAMES_ENABLE_TEXT_INFO, readableFrameName2);
					callback=function(state)
						if (state.type == K_BUTTON) then
							MobileFrames_ResetFrame[frameName2](state);
						elseif (state.checked) then
							MobileFrames_EnableToggle[frameName2](1);
						else
							MobileFrames_EnableToggle[frameName2](0);
						end
					end;
					setup={buttonText=RESET};
					feedback=function(state)
						if (state.type == K_BUTTON) then
							return format(MOBILE_FRAMES_RESET, readableFrameName2);
						elseif ( state.checked ) then 
							return format(MOBILE_FRAMES_ENABLED_TEXT, readableFrameName2)
						else
							return format(MOBILE_FRAMES_DISABLED_TEXT, readableFrameName2);
						end;
					end;
					default={
						checked=MobileFrames_MasterEnableList[frameName2];
					};
					disabled={
						checked=false;
					};
				}
			);
		end
	end
	
	table.insert(optionSet.options, 
		{
			id="SpecialSectionHeader";
			type=K_HEADER;
			text=MOBILE_FRAMES_SPECIAL_HEADER;
			helptext=MOBILE_FRAMES_SPECIAL_HEADER_INFO;
			difficulty=2;
		}
	);
	
	local alphaList = MobileFrames_GetTableKeyList(MobileFrames_SpecialFrames);
	table.sort(alphaList, MobileFrames_SortByReadableFrameName);
	for index, varPrefix in pairs(alphaList) do
		local data = MobileFrames_SpecialFrames[varPrefix];
		frameReadable  = GetReadableFrameName(varPrefix);
		local f = data.func;
		local r = data.reset;
		table.insert(optionSet.options,
			{
				id="EnableSpecial"..varPrefix;
				text=format(MOBILE_FRAMES_ENABLE_TEXT, frameReadable);
				helptext=format(MOBILE_FRAMES_ENABLE_TEXT_INFO, frameReadable);
				difficulty=2;
				type=K_BUTTON;
				check=true;
				callback=function(state)
					if (state.type == K_BUTTON) then
						r(state);
					elseif (state.checked) then 
						f(1);		
					else
						f(0);
					end
				end;
				setup={buttonText=RESET};
				feedback=function(state)
					if (state.type == K_BUTTON) then
						return format(MOBILE_FRAMES_RESET, frameReadable);
					elseif ( state.checked ) then 
						return format(MOBILE_FRAMES_ENABLED_TEXT, frameReadable)
					else
						return format(MOBILE_FRAMES_DISABLED_TEXT, frameReadable);
					end;
				end;
				default={checked=data.default;};
				disabled={checked=false};
			}
		);
	end			
	
	Khaos.registerOptionSet("frames", optionSet, true);

end

function MobileFrames_ToggleEnableGeneral(frameName, checked)
	if checked == nil then
		MobileFrames_MasterEnableList[frameName] = (not MobileFrames_MasterEnableList[frameName]);
	else
		MobileFrames_MasterEnableList[frameName] = (checked == 1);
	end
	local isSpecialFrame = (type(MobileFrames_SpecialFrames[frameName]) == "table");
	if not MobileFrames_MasterEnableList[frameName] then
		if (not isSpecialFrame) then
			MobileFrames_UIPanel_RemoveFrameRepositionIgnore(frameName);
		end
		if (getglobal(frameName.."MobileBar")) then	
			getglobal(frameName.."MobileBar"):EnableMouse(0);
		end
		if (checked == nil) then
			MobileFrames_Print(format(MOBILE_FRAMES_DISABLED_TEXT, frameName));
		end
	else
		if (not isSpecialFrame) then
			MobileFrames_UIPanel_AddFrameRepositionIgnore(frameName);
		end
		if (getglobal(frameName.."MobileBar")) then
			getglobal(frameName.."MobileBar"):EnableMouse(1);
		end
		if (checked == nil) then
			MobileFrames_Print(format(MOBILE_FRAMES_ENABLED_TEXT, frameName));
		end
	end
	if (checked == nil) and (not isSpecialFrame) then
		ShowUIPanel(getglobal(frameName));
	end
end


function MobileFrames_UIPanel_AddFrameRepositionIgnore(frameName)
	if not MobileFrames_UIPanelWindowBackup[frameName] then
		--MobileFrames_Print("Ignoring Reposition of "..frameName.." ("..UIPanelWindows[frameName].pushable..")")
		MobileFrames_UIPanelWindowBackup[frameName] = UIPanelWindows[frameName];
	end
	UIPanelWindows[frameName] = nil;
end


function MobileFrames_UIPanel_RemoveFrameRepositionIgnore(frameName)
	if MobileFrames_UIPanelWindowBackup[frameName] then
		UIPanelWindows[frameName] = MobileFrames_UIPanelWindowBackup[frameName];
		--MobileFrames_Print("Allowing Reposition of "..frameName.." ("..UIPanelWindows[frameName].pushable..")")
	end
	getglobal(frameName):SetUserPlaced(false);
	MobileFrames_UIPanelWindowBackup[frameName] = nil;
end

function MobileFrames_RightSide_SetResetFlag(frameName)
	--MobileFrames_Print("Ignoring Reposition of Right Side Frame: "..frameName);
	MobileFrames_RightSide_IsReset[frameName] = true;
end


function MobileFrames_RightSide_ClearResetFlag(frameName)
	--MobileFrames_Print("Allowing Reposition of Right Side Frame: "..frameName);
	MobileFrames_RightSide_IsReset[frameName] = nil;
end

function MobileFrames_RightSide_IsResetFlaged(frameName)
	return MobileFrames_RightSide_IsReset[frameName];
end

function MobileFrames_CloseWindows(ignoreCenter)
	local found;
	for index, value in pairs(MobileFrames_UIPanelWindowBackup) do
		if getglobal(index):IsVisible() then
			getglobal(index):Hide();
			found = 1;
		end
	end
	
	--if reseting sets to center make sure left isn't left defined but hidden
	local leftFrame = GetLeftFrame();
	if leftFrame then
		if not leftFrame:IsVisible() then
			SetLeftFrame(nil);
		end
	end
	
	local closed = SavedCloseWindows(ignoreCenter);
	return closed or found;
end


function MobileFrames_SlashCommandHandler(msg)
	local startpos, endpos, option, msg = string.find(msg, "(%w+)%s*(.*)");
	if (option == MOBILE_FRAMES_SLASH_LIST) then
		MobileFrames_List();
	elseif (option == MOBILE_FRAMES_SLASH_ENABLE) then
		MobileFrames_Enable(msg);
	elseif (option == MOBILE_FRAMES_SLASH_DISABLE) then
		MobileFrames_Disable(msg);
	elseif (option == MOBILE_FRAMES_SLASH_RESET) then
		MobileFrames_Reset(msg);
	elseif (option == MOBILE_FRAMES_SLASH_ANCHORS) then
		MobileFrames_ToggleAnchors();
	elseif (option == MOBILE_FRAMES_SLASH_SOUND) then
		MobileFrames_ToggleSound();
	elseif (option == MOBILE_FRAMES_SLASH_OFFSET) then
		MobileFrames_SetOffsets(msg);
	elseif (option == MOBILE_FRAMES_SLASH_ROLLSTACK) then
		MobileFrames_ToggleRollStack(msg);
	else
		MobileFrames_PrintColored(MOBILE_FRAMES_HELP_TITLE, 0.08, 0.16, 1.0); -- Deep Blue
		MobileFrames_PrintLines(
			MOBILE_FRAMES_HELP_SUMMARY,
			MOBILE_FRAMES_HELP_MAIN,
			MOBILE_FRAMES_HELP_LIST,
			MOBILE_FRAMES_HELP_ENABLE,
			MOBILE_FRAMES_HELP_DISABLE,
			MOBILE_FRAMES_HELP_RESET,
			MOBILE_FRAMES_HELP_ANCHORS,
			MOBILE_FRAMES_HELP_SOUND,
			MOBILE_FRAMES_HELP_UIPANEL_OFFSET,
			MOBILE_FRAMES_HELP_CONTAINERS_OFFSET,
			MOBILE_FRAMES_HELP_ROLLSTACK
		);
	end
end

function MobileFrames_PrintLines(...)
	local i=1;
	for i=1, select("#", ...) do
		DEFAULT_CHAT_FRAME:AddMessage(select(i, ...), 0.0, 1.0, 0.25); -- Default green
	end
end

function MobileFrames_Print(...)
	local lineText = "";
	for i=1, select("#", ...) do
		lineText = lineText..select(i, ...);
	end
	DEFAULT_CHAT_FRAME:AddMessage(lineText, 0.0, 1.0, 0.25); -- Default green
end

function MobileFrames_PrintColored(lineText, r, g, b)
	DEFAULT_CHAT_FRAME:AddMessage(lineText, r, g, b);
end

function MobileFrames_List()
	
	MobileFrames_PrintColored(MOBILE_FRAMES_LIST_MOVABLE_TITLE, 0.08, 0.16, 1.0); -- Deep Blue
	local frameReadable;
	local alphaList = MobileFrames_GetTableKeyList(MobileFrames_SpecialFrames);
	local templist = MobileFrames_GetTableKeyList(MobileFrames_MasterEnableList);
	for index, frameName in pairs(templist) do
		if (not MobileFrames_SpecialFrames[frameName]) then
			table.insert(alphaList, frameName);
		end
	end
	table.sort(alphaList, MobileFrames_SortByReadableFrameName);
	
	local i = 0;
	for index, frameName in pairs(alphaList) do
		frameReadable  = GetReadableFrameName(frameName);
		if (frameReadable) then
			MobileFrames_Print(frameName.." = "..frameReadable);
		else
			MobileFrames_Print(frameName);
		end
		i=i+1;
	end
	MobileFrames_Print(format(MOBILE_FRAMES_LIST_MOVABLE_TOTAL,i));
end


function MobileFrames_ListVisible()

	MobileFrames_PrintColored(MOBILE_FRAMES_LIST_VISIBLE_TITLE, 0.08, 0.16, 1.0); -- Deep Blue
	local frameReadable = "";
	local i = 0;
	for index, value in pairs(MobileFrames_UIPanelsVisible) do
		frameReadable  = GetReadableFrameName(index);
		MobileFrames_Print(frameReadable.." ("..value..")");
		i=i+1;
	end
	MobileFrames_Print(format(MOBILE_FRAMES_LIST_VISIBLE_TOTAL,i));
end


function MobileFrames_Enable(msg)
	-- Raise it to upper case for comparison purposes.
	local frameName;
	local found;
	local enableAll;
	local redraw;
	local frameReadable = "";
	if (type(msg) == "string") then
		frameName = string.upper(msg)
	end
	if (msg == "") or (not msg) or (msg == 0) then
		enableAll = true;
	end
	
	for varPrefix, data in pairs(MobileFrames_SpecialFrames) do
		frameReadable  = GetReadableFrameName(varPrefix);
		if (enableAll) or (frameName == string.upper(varPrefix)) or (frameName == string.upper(frameReadable)) then
			data.func(1);
			if (Khaos) then
				if (Khaos.getSetKey("MobileFrames","EnableSpecial"..varPrefix)) then
					Khaos.setSetKeyParameter("MobileFrames","EnableSpecial"..varPrefix, "checked", true);
				end
				redraw = true;
			end
			if (not enableAll) then
				MobileFrames_Print(format(MOBILE_FRAMES_ENABLED_TEXT, frameReadable));
			end
		end
	end
	
	for index, value in pairs(MobileFrames_MasterEnableList) do
		frameReadable  = GetReadableFrameName(index);
		if (enableAll) or (frameName == string.upper(index)) or (frameName == string.upper(frameReadable)) then
			found = 1;
			MobileFrames_EnableToggle[index](1);
			if (Khaos) then
				if (Khaos.getSetKey("MobileFrames","Enable"..index)) then
					Khaos.setSetKeyParameter("MobileFrames","Enable"..index, "checked", true);
				end
				redraw = true;
			end
			if not enableAll then
				MobileFrames_Print(format(MOBILE_FRAMES_ENABLED_TEXT, frameReadable));
				ShowUIPanel(getglobal(index));
				break;
			end
		end
	end
	if (Khaos) then
		if (KhaosFrame:IsVisible() and redraw) then
			Khaos.refresh(false, false, true);
		end
	end
	if enableAll then
		MobileFrames_Print(MOBILE_FRAMES_ENABLED_ALL_TEXT);
	end
end


function MobileFrames_Disable(msg)
	-- Raise it to upper case for comparison purposes.
	local frameName;
	local found;
	local disableAll;
	local redraw;
	local frameReadable = "";
	if (type(msg) == "string") then
		frameName = string.upper(msg)
	end
	if (msg == "") or (not msg) or (msg == 0) then
		disableAll = true;
	end
	
	for varPrefix, data in pairs(MobileFrames_SpecialFrames) do
		frameReadable  = GetReadableFrameName(varPrefix);
		if (disableAll) or (frameName == string.upper(varPrefix)) or (frameName == string.upper(frameReadable)) then
			data.func(0);
			if (Khaos) then
				if (Khaos.getSetKey("MobileFrames","EnableSpecial"..varPrefix)) then
					Khaos.setSetKeyParameter("MobileFrames","EnableSpecial"..varPrefix, "checked", false);
				end
				redraw = true;
			end
			if (not disableAll) then
				MobileFrames_Print(format(MOBILE_FRAMES_DISABLED_TEXT, frameReadable));
			end
		end
	end
	
	for index, value in pairs(MobileFrames_MasterEnableList) do
		frameReadable  = GetReadableFrameName(index);
		if (disableAll) or (frameName == string.upper(index)) or (frameName == string.upper(frameReadable)) then
			found = 1;
			MobileFrames_EnableToggle[index](0);
			if (Khaos) then
				if (Khaos.getSetKey("MobileFrames","Enable"..index)) then
					Khaos.setSetKeyParameter("MobileFrames","Enable"..index, "checked", false);
				end
				redraw = true;
			end
			if not disableAll then
				MobileFrames_Print(format(MOBILE_FRAMES_DISABLED_TEXT, frameReadable));
				ShowUIPanel(getglobal(index));
				break;
			end
		end
	end
	if (Khaos) then
		if (KhaosFrame:IsVisible() and redraw) then
			Khaos.refresh(false, false, true);
		end
	end
	if disableAll then
		MobileFrames_Print(MOBILE_FRAMES_DISABLED_ALL_TEXT);
	end
end


function MobileFrames_Reset(msg)
	-- Raise it to upper case for comparison purposes.
	local frameName = string.upper(msg)
	local found;
	local resetAll;
	local frameReadable  = "";
	if (msg == "") or (not msg) or (msg == 0) then
		resetAll = true;
	end
	
	for varPrefix, data in pairs(MobileFrames_SpecialFrames) do
		frameReadable  = GetReadableFrameName(varPrefix);
		if (resetAll) or (frameName == string.upper(varPrefix)) or (frameName == string.upper(frameReadable)) then
			data.reset();
			if (not resetAll) then
				MobileFrames_Print(format(MOBILE_FRAMES_RESET, frameReadable));
			end
		end
	end
	
	if (resetAll) or (frameName == "OPENMAILFRAME") then
		found = 1;
		if OpenMailFrame:IsVisible() then
			OpenMailFrame:Hide();
		end
		OpenMailFrame:ClearAllPoints();
		OpenMailFrame:SetPoint("TOPLEFT", "InboxFrame", "TOPRIGHT", -10, 0);
		if not resetAll then 
			frameReadable  = GetReadableFrameName("OpenMailFrame");
			MobileFrames_Print(format(MOBILE_FRAMES_RESET, frameReadable));
		end
	end
	
	for index, value in pairs(MobileFrames_UIPanelWindowBackup) do
		frameReadable  = GetReadableFrameName(index);
		if (resetAll) or (frameName == string.upper(index)) or (frameName == string.upper(frameReadable)) then
			found = 1;
			MobileFrames_UIPanel_RemoveFrameRepositionIgnore(index);
			if getglobal(index):IsVisible() then
				getglobal(index):Hide();
			end
			if not resetAll then 
				ShowUIPanel(getglobal(index));
				MobileFrames_Print(format(MOBILE_FRAMES_RESET, frameReadable));
				break;
			end
		end
	end
	
	UIParent_ManageFramePositions();
	
	if found and resetAll then
		MobileFrames_Print(MOBILE_FRAMES_RESET_ALL);
	elseif not found then
		-- If it's not found, it's unrecognized.  Tell the user.
		-- disabled due to confusing call on multiple reset
		-- MobileFrames_Print(MOBILE_FRAMES_ERROR);
	end
end

function MobileFrames_SetOffsets(msg)
	local redraw;
	msg = string.lower(msg);
	local startpos, endpos, option, value = string.find(msg, "(%w+) (%d+)");
	value = tonumber(value);
	if (option) and (value) then
		if (value >= 0) and (value <= 200) then
			if (option == MOBILE_FRAMES_SLASH_UIPANEL_OFFSET) then
				MobileFrames_SetUIPanelOffsetLeft(1, value);
				MobileFrames_Print(MOBILE_FRAMES_SET_UIPANEL_OFFSET..": "..value);
				if (Khaos) then
					Khaos.setSetKeyParameter("MobileFrames","SetUIPanelOffset", "checked", true);
					Khaos.setSetKeyParameter("MobileFrames","SetUIPanelOffset", "slider", value);
					redraw = true;
				end
			elseif (option == MOBILE_FRAMES_SLASH_CONTAINERS_OFFSET) then
				MobileFrames_SetContainerOffset(1, value);
				MobileFrames_Print(MOBILE_FRAMES_SET_CONTAINERS_OFFSET..": "..value);
				if (Khaos) then
					Khaos.setSetKeyParameter("MobileFrames","SetContainerOffset", "checked", true);
					Khaos.setSetKeyParameter("MobileFrames","SetContainerOffset", "slider", value);
					redraw = true;
				end
			end
		end
	end
	if (Khaos) then
		if (KhaosFrame:IsVisible() and redraw) then
			Khaos.refresh(false, false, true);
		end
	end
end


function MobileFrames_ShowUIPanel(frame, force)
	if ( not frame or frame:IsVisible() ) then
		return false;
	end
	-- if Mobile frame
	if MobileFrames_UIPanelWindowBackup[frame:GetName()] then
		-- if not pushable
		if MobileFrames_UIPanelWindowBackup[frame:GetName()].pushable == 0 then
			-- hide visible, non-pushable, mobile frames
			for frameName, value in pairs(MobileFrames_UIPanelsVisible) do
				if MobileFrames_UIPanelWindowBackup[frameName].pushable == 0 then
					getglobal(frameName):Hide();
				end
			end
			-- hide visible, non-pushable, left, standard UI Panel
			-- preserve any center frame
			local leftFrame = GetLeftFrame();
			if leftFrame then
				local panel = UIPanelWindows[leftFrame:GetName()];
				if panel then
					if panel.pushable == 0 then
						if GetCenterFrame() then
							MovePanelToLeft();
						else
							SetLeftFrame(nil);
						end
					end
				end
			end
		end
	end
	return true;
end


function MobileFrames_AddToVisibleList(frameName)
	if not MobileFrames_UIPanelsVisible[frameName] then
		if not MobileFrames_UIPanelWindowBackup[frameName] then
			--recently reset
			local left = GetLeftFrame();
			local center = GetCenterFrame();
			local doublewide = GetDoublewideFrame();
			if (left) then
				if left:GetName() == frameName then
					SetLeftFrame(nil);
				end
			end
			if (center) then
				if center:GetName() == frameName then
					SetCenterFrame(nil);
				end
			end
			if (doublewide) then
				if doublewide:GetName() == frameName then
					SetDoublewideFrame(nil);
				end
			end
			MobileFrames_UIPanel_AddFrameRepositionIgnore(frameName);
		end
		if MobileFrames_UIPanelWindowBackup[frameName] then
			MobileFrames_UIPanelsVisible[frameName] = MobileFrames_UIPanelWindowBackup[frameName].pushable;
		end
	end
end


function MobileFrames_RemoveFromVisibleList(frameName)
	MobileFrames_UIPanelsVisible[frameName] = nil;
end

function GetReadableFrameName(frameName)
	--makes the frame name readble and localizable
	if (MobileFrames_MultiSpecialFrames[frameName]) then
		frameName = MobileFrames_MultiSpecialFrames[frameName]
	end
	local frameReadable = MOBILE_FRAMES_FRAMEDESCRIPTIONS[frameName];
	if (not frameReadable) then
		frameReadable = frameName;
	end
	return frameReadable;
end

-- <= == == == == == == == == == == == == =>
-- => UIPanel Offsets Frames
-- <= == == == == == == == == == == == == =>

function MobileFrames_SetDoublewideFrame(frame)
	local oldFrame1 = UIParent.left;
	local oldFrame2 = UIParent.center;
	UIParent.doublewide = frame;
	UIParent.left = nil;
	UIParent.center = nil;

	if ( oldFrame1 ) then
		oldFrame1:Hide();
	end
	
	if ( oldFrame2 ) then
		oldFrame2:Hide();
	end

	if ( frame ) then
		frame:SetPoint("TOPLEFT", "UIParent", "TOPLEFT", UIPANEL_OFFSET_LEFT, -104);
		frame:Show();
	end
end

function MobileFrames_SetLeftFrame(frame)
	local oldFrame = UIParent.left;
	UIParent.left = frame;

	if ( oldFrame ) then
		oldFrame:Hide();
	end	

	if ( frame ) then
		frame:SetPoint("TOPLEFT", "UIParent", "TOPLEFT", UIPANEL_OFFSET_LEFT, -104);
		frame:Show();
	end
end

function MobileFrames_SetCenterFrame(frame, skipSetPoint)
	local oldFrame = UIParent.center;
	UIParent.center = frame;

	if ( oldFrame ) then
		oldFrame:Hide();
	end

	if ( frame ) then
		frame:Show();
		if ( not skipSetPoint ) then
			frame:SetPoint("TOPLEFT", "UIParent", "TOPLEFT", UIPANEL_OFFSET_LEFT+384, -104);
		end
		-- Hide all child windows
		local childWindow;
		for index, value in pairs(UIChildWindows) do
			childWindow = getglobal(value);
			if ( childWindow ) then
				childWindow:Hide();
			end
		end
	end
	
end

function MobileFrames_MovePanelToLeft()
	if ( UIParent.center ) then
		UIParent.center:SetPoint("TOPLEFT", "UIParent", "TOPLEFT", UIPANEL_OFFSET_LEFT, -104);
		SetLeftFrame(nil);
		UIParent.left = UIParent.center
		UIParent.center = nil;
	end
end

function MobileFrames_MovePanelToCenter()
	if ( UIParent.left ) then
		SetCenterFrame(nil);
		UIParent.left:SetPoint("TOPLEFT", "UIParent", "TOPLEFT", UIPANEL_OFFSET_LEFT+384, -104);
		UIParent.center = UIParent.left
		UIParent.left = nil;
	end
end

-- <= == == == == == == == == == == == == =>
-- => Mobile Container Frames
-- <= == == == == == == == == == == == == =>

function MobileFrames_updateContainerFrameAnchors()
	-- Adjust the start anchor for bags depending on the multibars
	UIParent_ManageRightSideFrames();
	local xOffset = CONTAINER_OFFSET_X;
	local uiScale = GetCVar("uiscale") + 0;
--	local screenHeight = GetScreenHeight();
	local screenHeight = 768;
	if ( GetCVar("useUiScale") == "1" ) then
		screenHeight = 768 / uiScale;
	end
	local freeScreenHeight = screenHeight - CONTAINER_OFFSET_Y;
	local lastBag = nil;
	local column = 0;
	for index, frameName in pairs(ContainerFrame1.bags) do
		local frame = getglobal(frameName);
		if (not frame.isMoving) then
			if (MobileFrames_MobileContainers) and (MobileFrames_ContainerPositionsByID[frame:GetID()]) then
				-- Bag has been previously moved
				local x = MobileFrames_ContainerPositionsByID[frame:GetID()][1];
				local y = MobileFrames_ContainerPositionsByID[frame:GetID()][2];
				frame:ClearAllPoints();
				frame:SetPoint(MobileFrames_ContainerPointSettings[MOBILEFRAMES_CONTAINER_POINT], MobileFrames_ContainerPointSettings[MOBILEFRAMES_CONTAINER_RELATIVETO], MobileFrames_ContainerPointSettings[MOBILEFRAMES_CONTAINER_RELATIVEPOINT], x, y );
				
			else
				-- freeScreenHeight determines when to start a new column of bags
				if ( not lastBag ) then
					-- First bag
					frame:ClearAllPoints();
					frame:SetPoint("BOTTOMRIGHT", "UIParent", "BOTTOMRIGHT", -xOffset, CONTAINER_OFFSET_Y);
				elseif ( freeScreenHeight < frame:GetHeight() ) then
					-- Start a new column
					column = column + 1;
					freeScreenHeight = UIParent:GetHeight() - CONTAINER_OFFSET_Y;
					frame:ClearAllPoints();
					frame:SetPoint("BOTTOMRIGHT", "UIParent", "BOTTOMRIGHT", -(column * CONTAINER_WIDTH) - xOffset, CONTAINER_OFFSET_Y);
				else
					-- Anchor to the previous bag
					frame:ClearAllPoints();
					frame:SetPoint("BOTTOMRIGHT", lastBag, "TOPRIGHT", 0, CONTAINER_SPACING);	
				end
				freeScreenHeight = freeScreenHeight - frame:GetHeight() - VISIBLE_CONTAINER_SPACING;
				--last bag is the last unpositioned bag (not yet dragged)
				lastBag = frameName;
			end
		end
	end
	-- This is used to position the unit tooltip
	local oldContainerPosition = OPEN_CONTAINER_POSITION;
	if ( ContainerFrame1.bagsShown == 0 ) then
		DEFAULT_TOOLTIP_POSITION = -13;
	else
		DEFAULT_TOOLTIP_POSITION = -((column + 1) * CONTAINER_WIDTH) - xOffset;
	end
	if ( DEFAULT_TOOLTIP_POSITION ~= oldContainerPosition and GameTooltip.default and GameTooltip:IsVisible() ) then
		GameTooltip:SetPoint("BOTTOMRIGHT", "UIParent", "BOTTOMRIGHT", DEFAULT_TOOLTIP_POSITION, 64);
	end
end

function MobileFrames_MarkContainerCoords(frame)
	local x = frame:GetLeft(); 
	local y = frame:GetTop(); 
	local coords = { x, y }; 
	MobileFrames_ContainerPositionsByID[frame:GetID()] = coords;
end

function MobileFrames_ContainerBarOnLoad(barFrame)
	--set to parent width
	barFrame:SetWidth(barFrame:GetParent():GetWidth());

	--subtract HitRectInsets/AbsInset/right value of parent stored in bar id
	--only needed since there's no GetRightHitRectInset()
	local widthOffeset = barFrame:GetID();
	if ( widthOffeset ) then
		barFrame:SetWidth(barFrame:GetWidth()-widthOffeset);
	end
end

function MobileFrames_EnableMobileContainers(checked) 
	if checked == nil then
		MobileFrames_MobileContainers = (not MobileFrames_MobileContainers);
	else
		MobileFrames_MobileContainers = (checked == 1);
	end
	local container;
	local bar;
	for i=1, 11 do
		container = getglobal("ContainerFrame"..i);
		bar = getglobal("ContainerFrame"..i.."MobileBar");
		container:ClearAllPoints();
		if container:IsVisible() then
			container:Hide();
		end
		if (MobileFrames_MobileContainers) then
			bar:EnableMouse(1);
		else
			bar:EnableMouse(0);
		end
	end
end

function MobileFrames_ResetMobileContainers()
	MobileFrames_ContainerPositionsByID = {};
	local bag;
	for i=1, 11 do
		bag = getglobal("ContainerFrame"..i);
		if bag:IsVisible() then
			bag:Hide();
		end
		bag:SetUserPlaced(false);
	end
end

-- <= == == == == == == == == == == == == =>
-- => Mobile Frame Anchors
-- <= == == == == == == == == == == == == =>

function MobileFrames_SideAnchor_OnShow(anchorFrame)
	if (MobileFrames_AnchorsSoundOn) then
		--PlaySoundFile("Sound\\Character\\Footsteps\\EnterWaterSplash\\EnterWaterMediumA.wav");
	end
	if ( (anchorFrame:GetParent():GetLeft()+(anchorFrame:GetParent():GetWidth()/2)) > UIParent:GetRight()/2 ) then
		anchorFrame:ClearAllPoints();
		anchorFrame:SetPoint("RIGHT", anchorFrame:GetParent():GetName(), "LEFT", anchorFrame.leftx, 0);
	else
		anchorFrame:ClearAllPoints();
		anchorFrame:SetPoint("LEFT", anchorFrame:GetParent():GetName(), "RIGHT", anchorFrame.rightx, 0);
	end
end

function MobileFrames_TopBottomAnchor_OnShow(anchorFrame)
	if (MobileFrames_AnchorsSoundOn) then
		--PlaySoundFile("Sound\\Character\\Footsteps\\EnterWaterSplash\\EnterWaterMediumA.wav");
	end
	if ( (anchorFrame:GetParent():GetBottom()+(anchorFrame:GetParent():GetHeight()/2)) < UIParent:GetTop()/2 ) then
		anchorFrame:ClearAllPoints();
		anchorFrame:SetPoint("BOTTOM", anchorFrame:GetParent():GetName(), "TOP", 0, anchorFrame.topy);
	else
		anchorFrame:ClearAllPoints();
		anchorFrame:SetPoint("TOP", anchorFrame:GetParent():GetName(), "BOTTOM", 0, anchorFrame.bottomy);
	end
end

function MobileFrames_Anchor_OnMouseUp(anchorFrame)
	MobileFrames_BarStopDrag(anchorFrame);
end

function MobileFrames_Anchor_OnMouseDown(anchorFrame)
	if (arg1 == "RightButton") and (IsShiftKeyDown()) then
		MobileFramesDropDown.displayMode = "MENU";
		ToggleDropDownMenu(1, anchorFrame:GetParent():GetName(), MobileFramesDropDown, anchorFrame:GetName());
	else
		MobileFrames_BarStartDrag(this);
	end
end

function MobileFrames_Anchor_OnHide(anchorFrame)
	MobileFrames_BarStopDrag(anchorFrame);
	if (MobileFrames_AnchorsSoundOn) and (not MobileFrames_AnchorsUp) then
		PlaySoundFile("Sound\\Character\\Footsteps\\EnterWaterSplash\\EnterWaterMediumA.wav");
	end
end

function MobileFrames_Anchor_OnLoad(anchorFrame)
	
	anchorFrame.rightx = 0;
	anchorFrame.leftx = 0;
	anchorFrame.topy = 0;
	anchorFrame.bottomy = 0;
				
	if (not anchorFrame:GetParent():IsMovable()) then
		anchorFrame:GetParent():SetMovable(1);
	end

	--set default enable status
	MobileFrames_MasterAnchorEnableList[anchorFrame:GetParent():GetName()] = MobileFrames_EnabledByDefault;
	
end

function MobileFrames_ToggleSound()

	MobileFrames_EnableAnchorSound();
	
	if (Khaos) then
		local onOff;
		if (MobileFrames_AnchorsSoundOn) then
			onOff = true;
		else
			onOff = false;
		end
		Khaos.updateSetKeys("MobileFrames",{EnableSound={checked=onOff}})
		if KhaosFrame:IsVisible() then
			Khaos.refresh(false, false, true);
		end
	end

end

function MobileFrames_EnableAnchorSound(checked)
	if checked == nil then
		MobileFrames_AnchorsSoundOn = (not MobileFrames_AnchorsSoundOn);
	else
		MobileFrames_AnchorsSoundOn = (checked == 1);
	end
end

function MobileFrames_AnchorToggleEnableGeneral(frameName, checked)
	if checked == nil then
		MobileFrames_MasterAnchorEnableList[frameName] = (not MobileFrames_MasterAnchorEnableList[frameName]);
	else
		MobileFrames_MasterAnchorEnableList[frameName] = (checked == 1);
	end
	if getglobal(frameName.."MobileButton"):IsVisible() then
		getglobal(frameName.."MobileButton"):Hide();
	end
	if not MobileFrames_MasterAnchorEnableList[frameName] then
		if getglobal(frameName.."MobileButton"):IsVisible() then
			getglobal(frameName.."MobileButton"):Hide();
		end
		if (checked == nil) then
			MobileFrames_Print(format(MOBILE_FRAMES_DISABLED_TEXT, frameName));
		end
	else
		if ( not getglobal(frameName.."MobileButton"):IsVisible() ) and (MobileFrames_AnchorsUp) then
			getglobal(frameName.."MobileButton"):Show();
		end
		if (checked == nil) then
			MobileFrames_Print(format(MOBILE_FRAMES_ENABLED_TEXT, frameName));
		end
	end
end

function MobileFrames_ToggleAnchors()
	
	if (MobileFrames_AnchorsUp) then
		MobileFrames_AnchorsUp = false;
		MultiActionBar_HideAllGrids();
		PopNUI_Override = Previous_PopNUI_Override;
		TransNUI_Override = Previous_TransNUI_Override;
	else
		MobileFrames_AnchorsUp = true;
		MultiActionBar_ShowAllGrids();
		Previous_PopNUI_Override = PopNUI_Override;
		Previous_TransNUI_Override = TransNUI_Override;
		PopNUI_Override = true;
		TransNUI_Override = true;
	end
	
	for frameName, enabled in pairs(MobileFrames_MasterAnchorEnableList) do
		if (MobileFrames_AnchorsUp) and (enabled) then
			getglobal(frameName.."MobileButton"):Show();
		else
			getglobal(frameName.."MobileButton"):Hide();
		end
	end
	
	UIParent_ManageFramePositions();

end

-- <= == == == == == == == == == == == == =>
-- => Mobile Anchor Frames Reset
-- <= == == == == == == == == == == == == =>

function MobileFrames_EnableMobilePartyMemberFrames(checked) 
	MobileFrames_AnchorToggleEnableGeneral("PartyMemberFrame1", checked);
	MobileFrames_AnchorToggleEnableGeneral("PartyMemberFrame2", checked);
	MobileFrames_AnchorToggleEnableGeneral("PartyMemberFrame3", checked);
	MobileFrames_AnchorToggleEnableGeneral("PartyMemberFrame4", checked);
end

function MobileFrames_ResetMobilePartyMemberFrames()
	local wasMoving = false;
	local frame;
	for i=1, 4 do
		frame = getglobal("PartyMemberFrame"..i);
		if ( frame.isMoving ) then
			frame:StopMovingOrSizing();
			frame.isMoving = false;
			wasMoving = true;
		end
		frame:SetUserPlaced(false);
	end
	if (not wasMoving) then
		PartyMemberFrame1:ClearAllPoints();
		PartyMemberFrame1:SetPoint("TOPLEFT", "UIParent", "TOPLEFT", 10, -128);
		PartyMemberFrame2:ClearAllPoints();
		PartyMemberFrame2:SetPoint("TOPLEFT", "PartyMemberFrame1", "BOTTOMLEFT", 0, -10);
		PartyMemberFrame3:ClearAllPoints();
		PartyMemberFrame3:SetPoint("TOPLEFT", "PartyMemberFrame2", "BOTTOMLEFT", 0, -10);
		PartyMemberFrame4:ClearAllPoints();
		PartyMemberFrame4:SetPoint("TOPLEFT", "PartyMemberFrame3", "BOTTOMLEFT", 0, -10);
	end
end

function MobileFrames_ResetMobilePlayerFrame()
	if ( PlayerFrame.isMoving ) then
		PlayerFrame:StopMovingOrSizing();
		PlayerFrame.isMoving = false;
	else
		PlayerFrame:ClearAllPoints();
		PlayerFrame:SetUserPlaced(false);
		PlayerFrame:SetPoint("TOPLEFT", "UIParent", "TOPLEFT", -19, -4);
	end
end

function MobileFrames_ResetMobileTargetFrame()
	if ( TargetFrame.isMoving ) then
		TargetFrame:StopMovingOrSizing();
		TargetFrame.isMoving = false;
	else
		TargetFrame:ClearAllPoints();
		TargetFrame:SetUserPlaced(false);
		TargetFrame:SetPoint("TOPLEFT", "UIParent", "TOPLEFT", 250, -4);
	end
end

function MobileFrames_ResetMobileTargetofTargetFrame()
	if ( TargetofTargetFrame.isMoving ) then
		TargetofTargetFrame:StopMovingOrSizing();
		TargetofTargetFrame.isMoving = false;
	else
		TargetofTargetFrame:ClearAllPoints();
		TargetofTargetFrame:SetUserPlaced(false);
		TargetofTargetFrame:SetPoint("BOTTOMRIGHT", "TargetFrame", "BOTTOMRIGHT", -35, -10);
	end
end

function MobileFrames_ResetMobilePetFrame()
	if ( PetFrame.isMoving ) then
		PetFrame:StopMovingOrSizing();
		PetFrame.isMoving = false;
	else
		PetFrame:ClearAllPoints();
		PetFrame:SetUserPlaced(false);
		PetFrame:SetPoint("TOPLEFT", "PlayerFrame", "TOPLEFT", 80, -60);
	end
end

function MobileFrames_EnableMobileBottomMultiBars(checked) 
	MobileFrames_AnchorToggleEnableGeneral("MultiBarBottomRight", checked);
	MobileFrames_AnchorToggleEnableGeneral("MultiBarBottomLeft", checked);
end

function MobileFrames_ResetMobileBottomMultiBars()
	if ( MultiBarBottomLeft.isMoving ) or ( MultiBarBottomRight.isMoving ) then
		MultiBarBottomLeft:StopMovingOrSizing();
		MultiBarBottomLeft.isMoving = false;
		MultiBarBottomRight:StopMovingOrSizing();
		MultiBarBottomRight.isMoving = false;
	else
		MultiBarBottomLeft:ClearAllPoints();
		MultiBarBottomLeft:SetUserPlaced(false);
		UIParent_ManageFramePositions();
		MultiBarBottomLeft.isReset = true;
		MultiBarBottomRight:ClearAllPoints();
		MultiBarBottomRight:SetUserPlaced(false);
		MultiBarBottomRight:SetPoint("LEFT", "MultiBarBottomLeft", "RIGHT", 10, 0);
		MultiBarBottomRight.isReset = true;
		if (UIPARENT_MANAGED_FRAME_POSITIONS["PETACTIONBAR_YPOS"]) then
			UIPARENT_MANAGED_FRAME_POSITIONS["PETACTIONBAR_YPOS"].bottomLeft = 43;
		end
		if (UIPARENT_MANAGED_FRAME_POSITIONS["ShapeshiftBarFrame"]) then
			UIPARENT_MANAGED_FRAME_POSITIONS["ShapeshiftBarFrame"].bottomLeft = 45;
		end
		UIParent_ManageFramePositions();
	end
end

function MobileFrames_EnableMobileSideMultiBars(checked) 
	MobileFrames_AnchorToggleEnableGeneral("MultiBarLeft", checked);
	MobileFrames_AnchorToggleEnableGeneral("MultiBarRight", checked);
end

function MobileFrames_ResetMobileSideMultiBars()
	if ( MultiBarLeft.isMoving ) or ( MultiBarRight.isMoving ) then
		MultiBarLeft:StopMovingOrSizing();
		MultiBarLeft.isMoving = false;
		MultiBarRight:StopMovingOrSizing();
		MultiBarRight.isMoving = false;
	else
		MultiBarRight:ClearAllPoints();
		MultiBarRight:SetUserPlaced(false);
		MultiBarRight:SetPoint("BOTTOMRIGHT", "UIParent", "BOTTOMRIGHT", -7, 98);
		MultiBarLeft:ClearAllPoints();
		MultiBarLeft:SetUserPlaced(false);
		MultiBarLeft:SetPoint("TOPRIGHT", "MultiBarRight", "TOPLEFT", -5, 0);
	end
end

function MobileFrames_ResetMobileMinimapCluster()
	if ( MinimapCluster.isMoving ) then
		MinimapCluster:StopMovingOrSizing();
		MinimapCluster.isMoving = false;
	else
		MinimapCluster:ClearAllPoints();
		MinimapCluster:SetUserPlaced(false);
		MinimapCluster:SetPoint("TOPRIGHT", "UIParent", "TOPRIGHT", 0, 0);
	end
end

function MobileFrames_ResetMobileBuffFrame()
	if ( TemporaryEnchantFrame.isMoving ) then
		TemporaryEnchantFrame:StopMovingOrSizing();
		TemporaryEnchantFrame.isMoving = false;
	else
		TemporaryEnchantFrame:ClearAllPoints();
		TemporaryEnchantFrame:SetUserPlaced(false);
		if (TicketStatusFrame:IsVisible()) then
			TemporaryEnchantFrame:SetPoint("TOPRIGHT", "UIParent", "TOPRIGHT", -205, (-TicketStatusFrame:GetHeight()));
		else
			TemporaryEnchantFrame:SetPoint("TOPRIGHT", "UIParent", "TOPRIGHT", -205, -13);
		end
	end
end

function MobileFrames_ResetMobileTicketStatusFrame()
	if ( TicketStatusFrame.isMoving ) then
		TicketStatusFrame:StopMovingOrSizing();
		TicketStatusFrame.isMoving = false;
	else
		TicketStatusFrame:ClearAllPoints();
		TicketStatusFrame:SetUserPlaced(false);
		TicketStatusFrame:SetPoint("TOPRIGHT", "UIParent", "TOPRIGHT", -180, 0);
	end
end

function MobileFrames_ResetMobileWorldStateScoreFrame()
	if ( WorldStateScoreFrame.isMoving ) then
		WorldStateScoreFrame:StopMovingOrSizing();
		WorldStateScoreFrame.isMoving = false;
	else
		WorldStateScoreFrame:ClearAllPoints();
		WorldStateScoreFrame:SetUserPlaced(false);
		WorldStateScoreFrame:SetPoint("CENTER", "UIParent", "CENTER", 55, 0);
	end
end

function MobileFrames_ResetMobileUIErrorsFrame()
	UIErrorsFrame:ClearAllPoints();
	UIErrorsFrame:SetUserPlaced(false);
	UIErrorsFrame:SetPoint("TOP", "UIParent", "TOP", 0, -122);
	UIErrorsFrame.isReset = true;
end

-- <= == == == == == == == == == == == == =>
-- => UIParent_ManageFramePositions Hook
-- <= == == == == == == == == == == == == =>

function MobileFrames_UIParent_ManageFramePositions_before()
	if (MultiBarBottomLeft:IsShown()) and (MultiBarBottomLeft:IsUserPlaced()) then
		if (UIPARENT_MANAGED_FRAME_POSITIONS["PETACTIONBAR_YPOS"]) then
			--saved bottomLeft = 43
			UIPARENT_MANAGED_FRAME_POSITIONS["PETACTIONBAR_YPOS"].bottomLeft = 0;
		end
		if (UIPARENT_MANAGED_FRAME_POSITIONS["ShapeshiftBarFrame"]) then
			--saved bottomLeft = 45
			UIPARENT_MANAGED_FRAME_POSITIONS["ShapeshiftBarFrame"].bottomLeft = 0;
		end
	end
end

function MobileFrames_UIParent_ManageFramePositions_after()
	if (MultiBarBottomLeft:IsShown()) and (not MultiBarBottomLeft:IsUserPlaced()) then
		SlidingActionBarTexture0:Hide();
		SlidingActionBarTexture1:Hide();
	else
		SlidingActionBarTexture0:Show();
		SlidingActionBarTexture1:Show();
	end
	if (MultiBarBottomLeft:IsShown() or MultiBarBottomLeft:IsUserPlaced()) then
		ShapeshiftBarLeft:Hide();
		ShapeshiftBarRight:Hide();
		ShapeshiftBarMiddle:Hide();
		for i=1, GetNumShapeshiftForms() do
			getglobal("ShapeshiftButton"..i.."NormalTexture"):SetWidth(50);
			getglobal("ShapeshiftButton"..i.."NormalTexture"):SetHeight(50);
		end
	else
		if ( GetNumShapeshiftForms() > 2 ) then
			ShapeshiftBarMiddle:Show();
		end
		ShapeshiftBarLeft:Show();
		ShapeshiftBarRight:Show();
		for i=1, GetNumShapeshiftForms() do
			getglobal("ShapeshiftButton"..i.."NormalTexture"):SetWidth(64);
			getglobal("ShapeshiftButton"..i.."NormalTexture"):SetHeight(64);
		end
	end
end

-- <= == == == == == == == == == == == == =>
-- => Pet/Shapeshift/Aura Bar Position Update
-- <= == == == == == == == == == == == == =>

function MobileFrames_PetActionBar_UpdatePosition()
	if (PetActionBarFrame:IsUserPlaced()) then
		SlidingActionBarTexture0:Hide();
		SlidingActionBarTexture1:Hide();
		return;
	else
		PetActionBarFrame:ClearAllPoints();
		PetActionBarFrame:SetUserPlaced(false);
		UIParent_ManageFramePositions();
	end
end

function MobileFrames_PetActionBarFrame_OnUpdate()
	if (not PetActionBarFrame:IsUserPlaced()) then
		return true;
	end
end

function MobileFrames_ShapeshiftBar_UpdatePosition()
	if (ShapeshiftBarFrame:IsUserPlaced()) then
		ShapeshiftBarLeft:Hide();
		ShapeshiftBarRight:Hide();
		ShapeshiftBarMiddle:Hide();
	else
		ShapeshiftBarFrame:ClearAllPoints();
		ShapeshiftBarFrame:SetUserPlaced(false);
		UIParent_ManageFramePositions();
	end
end

function MobileFrames_MultiBarBottomLeft_IsReset()
	if ( not MultiBarBottomLeft:GetCenter() ) or ( not PetActionBarFrame:GetLeft() )  or ( not ActionButton1:GetTop() ) then
		if  ( MultiBarBottomLeft:IsVisible() ) then
			return true;
		else
			return false;
		end
	end
	if  ( MultiBarBottomLeft:IsVisible() ) and
		( MultiBarBottomLeft:GetCenter() < PetActionBarFrame:GetRight() ) and 
		( MultiBarBottomLeft:GetCenter() > PetActionBarFrame:GetLeft() ) and
		( MultiBarBottomLeft:GetTop() < ActionButton1:GetTop()+PetActionBarFrame:GetHeight()+MultiBarBottomLeft:GetHeight() )
		then
		return true;
	else
		return false;
	end
end

-- <= == == == == == == == == == == == == =>
-- => Special Frame Offsets
-- <= == == == == == == == == == == == == =>

function MobileFrames_UIParent_ManageRightSideFrames(setQWFPoint, setDFPoint, setGLFPoint, setQTFPoint)
	local anchorX = 0;
	local anchorY = 0;
	
	-- Update group loot frame anchor
	if (setGLFPoint) or (MobileFrames_RightSide_IsResetFlaged("GroupLootFrame1")) then
		GroupLootFrame1:ClearAllPoints();
		GroupLootFrame1:SetUserPlaced(false);
		if ( MultiBarBottomRight:IsVisible() or MultiBarBottomLeft:IsVisible() ) then
			GroupLootFrame1:SetPoint("BOTTOM", "UIParent", "BOTTOM", 0, 102);
		else
			GroupLootFrame1:SetPoint("BOTTOM", "UIParent", "BOTTOM", 0, 60);
		end
		MobileFrames_RightSide_SetResetFlag("GroupLootFrame1");
	end
	
	-- Update tutorial anchor
	if ( MultiBarBottomRight:IsVisible() or MultiBarBottomLeft:IsVisible() ) then
		TutorialFrameParent:SetPoint("BOTTOM", "UIParent", "BOTTOM", 0, 94);
	else
		TutorialFrameParent:SetPoint("BOTTOM", "UIParent", "BOTTOM", 0, 52);
	end
	
	MobileFrames_FramerateLabelReset(true);
	
	-- Update bag anchor
	if (PopNUI_UIParent_ManageRightSideFrames) then
		PopNUI_UIParent_ManageRightSideFrames()
	elseif (Eclipse) and (Eclipse.UIParent_ManageRightSideFrames) then
		Eclipse.UIParent_ManageRightSideFrames();
	else
		if ( MultiBarBottomRight:IsVisible() ) then
			CONTAINER_OFFSET_Y = 97;
		else
			CONTAINER_OFFSET_Y = 70;
		end
	end
	
	-- Setup x anchor
	if (CONTAINER_OFFSET_X_SET) then
		CONTAINER_OFFSET_X = CONTAINER_OFFSET_X_SET;
	elseif (PopNUI_UIParent_ManageRightSideFrames) then
		PopNUI_UIParent_ManageRightSideFrames()
	elseif (Eclipse) and (Eclipse.UIParent_ManageRightSideFrames) then
		Eclipse.UIParent_ManageRightSideFrames();
	else
		if ( MultiBarLeft:IsVisible() ) then
			CONTAINER_OFFSET_X = 90;
		elseif ( MultiBarRight:IsVisible() ) then
			CONTAINER_OFFSET_X = 45;
		else
			CONTAINER_OFFSET_X = 0;
		end
	end
	anchorX = CONTAINER_OFFSET_X;
	-- Setup y anchors
	if (setQTFPoint) or (MobileFrames_RightSide_IsResetFlaged("QuestTimerFrame")) then
		QuestTimerFrame:ClearAllPoints();
		QuestTimerFrame:SetUserPlaced(false);
		QuestTimerFrame:SetPoint("TOPRIGHT", "MinimapCluster", "BOTTOMRIGHT", -anchorX, anchorY);
		MobileFrames_RightSide_SetResetFlag("QuestTimerFrame");
	end
	if (MobileFrames_RightSide_IsResetFlaged("QuestTimerFrame")) and (QuestTimerFrame:IsVisible()) then
		anchorY = anchorY - QuestTimerFrame:GetHeight();
	end
	if (setDFPoint) or (MobileFrames_RightSide_IsResetFlaged("DurabilityFrame")) then
		DurabilityFrame:ClearAllPoints();
		DurabilityFrame:SetUserPlaced(false);
		DurabilityFrame:SetPoint("TOPRIGHT", "MinimapCluster", "BOTTOMRIGHT", -anchorX-40, anchorY);
		MobileFrames_RightSide_SetResetFlag("DurabilityFrame");
	end
	--DurabilityFrame:Show();
	if (MobileFrames_RightSide_IsResetFlaged("DurabilityFrame")) and (DurabilityFrame:IsVisible()) then
		anchorY = anchorY - DurabilityFrame:GetHeight();
	end
	if (setQWFPoint) or (MobileFrames_RightSide_IsResetFlaged("QuestWatchFrame")) then
		QuestWatchFrame:ClearAllPoints();
		if (QuestWatchFrame:IsMovable()) then
			QuestWatchFrame:SetUserPlaced(false);
		end
		QuestWatchFrame:SetPoint("TOPRIGHT", "MinimapCluster", "BOTTOMRIGHT", -anchorX, anchorY);
		MobileFrames_RightSide_SetResetFlag("QuestWatchFrame");
	end
end

--orig_DurabilityFrame_Hide = DurabilityFrame.Hide;
--DurabilityFrame.Hide = function(self) MobileFrames_Print(this:GetName(), " is hiding the DurabilityFrame");DurabilityFrame.Hide(self) end;

function MobileFrames_SetContainerOffset(checked, value)
	CONTAINER_OFFSET_X_SET = nil;
	if (type(value) == "number") and (checked == 1) then
		if (value >= 0) then
			CONTAINER_OFFSET_X_SET = value;
			if (not Khaos) then
				MobileFrames_ContainerOffsetMarker_Show();
			end
		end
	end
end

function MobileFrames_ContainerOffsetMarker_Show()
	if (type(CONTAINER_OFFSET_X_SET) == "number") then
		MobileOffsetMarker:ClearAllPoints();
		MobileOffsetMarker:SetPoint("CENTER", "UIParent", "RIGHT", -CONTAINER_OFFSET_X_SET, 0);
		MobileOffsetMarker:Show();
		MobileFrames_OffsetMarker_Fade();
	end
end

function MobileFrames_SetUIPanelOffsetLeft(checked, value)
	UIPANEL_OFFSET_LEFT = 0;
	if (type(value) == "number") and (checked == 1) then
		if (value >= 0) then
			UIPANEL_OFFSET_LEFT = value;
			if (not Khaos) then
				MobileFrames_UIPanelOffsetMarker_Show();
			end
		end
	end
end

function MobileFrames_UIPanelOffsetMarker_Show()
	if (type(UIPANEL_OFFSET_LEFT) == "number") then
		MobileOffsetMarker:ClearAllPoints();
		MobileOffsetMarker:SetPoint("CENTER", "UIParent", "LEFT", UIPANEL_OFFSET_LEFT, 0);
		MobileOffsetMarker:Show();
		MobileFrames_OffsetMarker_Fade();
	end
end

function MobileFrames_OffsetMarker_Fade()
	if (MobileOffsetMarker:IsVisible()) then
		MobileOffsetMarker:SetAlpha(1);
		MobileOffsetMarker.counter = 80; -- ~ 2 sec timer
		MobileOffsetMarker.fadeCount = 40;  -- fade when ~ 1 sec left
		MobileOffsetMarker.isFading = true;
	end
end

function MobileFrames_OffsetMarker_OnLoad()
	--this.counter = 0;
end

function MobileFrames_OffsetMarker_Hide()
	MobileOffsetMarker.isFading = false;
	MobileOffsetMarker.counter = nil;
	MobileOffsetMarker.fadeCount = nil;
	MobileOffsetMarker:Hide();
end

function MobileFrames_OffsetMarker_OnUpdate()
	if (this.isFading) then
		if (type(this.counter) == "number") then
			if (this.counter > 0) then
				this.counter = this.counter - 1;
				if (type(this.fadeCount) == "number") then
					if (this.counter < this.fadeCount) then
						this:SetAlpha(this.counter/this.fadeCount);
					end
				end
			else
				this.counter = nil;
				this.fadeCount = nil;
			end
		else
			this.isFading = false;
			this:Hide()
			this:SetAlpha(1);
		end
	end
end

-- <= == == == == == == == == == == == == =>
-- => Mobile Framerate
-- <= == == == == == == == == == == == == =>

function MobileFrames_ToggleFramerateMobileBar()
	if ( FramerateLabelMobileBar and FramerateLabel:IsVisible() ) then
		FramerateLabelMobileBar:Show();
	else
		FramerateLabelMobileBar:Hide();
	end
end

function MobileFrames_TurnOnFPSMove(toggle)
	-- Move the FPS
	if (toggle == 1) then
		FramerateLabelMobileBar:ClearAllPoints();
		FramerateLabelMobileBar:SetPoint("TOPLEFT", "WorldFrame", "TOPLEFT", 0, 0);
	else
		FramerateLabelMobileBar:ClearAllPoints();
		FramerateLabelMobileBar:SetPoint("BOTTOM", "WorldFrame", "BOTTOM", 0, 64);
	end
end

function MobileFrames_FramerateLabelReset(passive)
	if (FramerateLabelMobileBar) then
		local bottom;
		local center = math.abs(WorldFrame:GetCenter() - FramerateLabelMobileBar:GetCenter());
		if ( MultiBarBottomRight:IsVisible() or MultiBarBottomLeft:IsVisible() ) then
			bottom = math.abs(64 - FramerateLabelMobileBar:GetBottom());
			if (not passive) or (bottom <= 4 and center <= 4) then
				FramerateLabelMobileBar:ClearAllPoints();
				FramerateLabelMobileBar:SetUserPlaced(false);
				FramerateLabelMobileBar:SetPoint("BOTTOM", "WorldFrame", "BOTTOM", 0, 104);
			end
		else
			bottom = math.abs(104 - FramerateLabelMobileBar:GetBottom());
			if (not passive) or (bottom <= 4 and center <= 4) then
				FramerateLabelMobileBar:ClearAllPoints();
				FramerateLabelMobileBar:SetUserPlaced(false);
				FramerateLabelMobileBar:SetPoint("BOTTOM", "WorldFrame", "BOTTOM", 0, 64);
			end
		end
	end
end

-- <= == == == == == == == == == == == == =>
-- => Mobile Buffs Reposition Override
-- <= == == == == == == == == == == == == =>

function MobileFrames_TicketStatusFrame_OnEvent()
	if ( event == "PLAYER_ENTERING_WORLD" ) then
		GetGMTicket();
	else
		if ( arg1 ~= 0 ) then		
			this:Show();
			if (false) then -- Fix when they add user repositioned
				TemporaryEnchantFrame:SetPoint("TOPRIGHT", this:GetParent():GetName(), "TOPRIGHT", -205, (-this:GetHeight()));
			end
			refreshTime = GMTICKET_CHECK_INTERVAL;
		else
			this:Hide();
			if (false) then -- Fix when they add user repositioned
				TemporaryEnchantFrame:SetPoint("TOPRIGHT", "UIParent", "TOPRIGHT", -180, -13);
			end
		end
	end	
end

-- <= == == == == == == == == == == == == =>
-- => Mobile GroupLootFrame Stacking
-- <= == == == == == == == == == == == == =>

function MobileFrames_ToggleRollStack()

	if (MobileFrames_RollStackDown) then
		MobileFrames_RollStackDown = nil;
		MobileFrames_SetDownwardRollWindowStack(0);
	else
		MobileFrames_RollStackDown = true;
		MobileFrames_SetDownwardRollWindowStack(1);
	end

end

function MobileFrames_SetDownwardRollWindowStack(toggle)
	if (toggle == 1) then
		GroupLootFrame2:ClearAllPoints();
		GroupLootFrame2:SetPoint("TOP", "GroupLootFrame1", "BOTTOM", 0, -3);
		GroupLootFrame3:ClearAllPoints();
		GroupLootFrame3:SetPoint("TOP", "GroupLootFrame2", "BOTTOM", 0, -3);
		GroupLootFrame4:ClearAllPoints();
		GroupLootFrame4:SetPoint("TOP", "GroupLootFrame3", "BOTTOM", 0, -3);
	else
		GroupLootFrame2:ClearAllPoints();
		GroupLootFrame2:SetPoint("BOTTOM", "GroupLootFrame1", "TOP", 0, 3);
		GroupLootFrame3:ClearAllPoints();
		GroupLootFrame3:SetPoint("BOTTOM", "GroupLootFrame2", "TOP", 0, 3);
		GroupLootFrame4:ClearAllPoints();
		GroupLootFrame4:SetPoint("BOTTOM", "GroupLootFrame3", "TOP", 0, 3);
	end
end

-- <= == == == == == == == == == == == == =>
-- => Mobile Casting Bar
-- <= == == == == == == == == == == == == =>

function MobileFrames_CastingBarFrame_Reset()
	CastingBarFrame:SetUserPlaced(false);
	CastingBarFrame:ClearAllPoints();
	--CastingBarFrame_UpdatePosition();
	UIParent_ManageFramePositions();
end

-- <= == == == == == == == == == == == == =>
-- => Mobile Main Menu Bar
-- <= == == == == == == == == == == == == =>

function MobileFrames_MobileMainMenuBar_Reset()
	MainMenuBar:ClearAllPoints();
	MainMenuBar:SetUserPlaced(false);
	MainMenuBar:SetPoint("BOTTOM", "UIParent", "BOTTOM");
	MainMenuBar.isReset = true;
end

function MobileFrames_MobileMainBackpackButtons_Reset()
	MainMenuBarBackpackButton:ClearAllPoints();
	MainMenuBarBackpackButton:SetUserPlaced(false);
	MainMenuBarBackpackButton:SetPoint("BOTTOMRIGHT", "MainMenuBarArtFrame", "BOTTOMRIGHT", -6, 2);
	MainMenuBarBackpackButton.isReset = true;
end

function MobileFrames_MobileCharacterMicroButtons_Reset()
	CharacterMicroButton:ClearAllPoints();
	CharacterMicroButton:SetUserPlaced(false);
	CharacterMicroButton:SetPoint("BOTTOMLEFT", "MainMenuBarArtFrame", "BOTTOMLEFT", 552, 2);
	CharacterMicroButton.isReset = true;
end

function MobileFrames_MobileActionButtons_Reset()
	ActionButton1:ClearAllPoints();
	ActionButton1:SetUserPlaced(false);
	ActionButton1:SetPoint("BOTTOMLEFT", "MainMenuBarArtFrame", "BOTTOMLEFT", 8, 4);
	ActionButton1.isReset = true;
end

function MobileFrames_MobileShapeshiftBarFrame_Reset()
	ShapeshiftBarFrame:SetUserPlaced(false);
	ShapeshiftBarFrame.isReset = true;
	ShapeshiftBar_UpdatePosition();
end

function MobileFrames_MobilePetActionBarFrame_Reset()
	PetActionBarFrame:SetUserPlaced(false);
	PetActionBarFrame.isReset = true;
	PetActionBarFrame.timeToSlide = 0;
	PetActionBarFrame.mode = "none";
end


-- <= == == == == == == == == == == == == =>
-- => Menu
-- <= == == == == == == == == == == == == =>

function MobileFramesDropDown_LoadDropDownMenu()
	--Title
	local info = {};
	info.text = GetReadableFrameName(UIDROPDOWNMENU_MENU_VALUE);
	info.notClickable = 1;
	info.isTitle = 1;
	UIDropDownMenu_AddButton(info, 1);
	
	--Reset
	local info = {};
	info.text = RESET;
	info.value = "Reset";
	info.func = function()
		if (MobileFrames_MultiSpecialFrames[UIDROPDOWNMENU_MENU_VALUE]) then
			MobileFrames_Reset(MobileFrames_MultiSpecialFrames[UIDROPDOWNMENU_MENU_VALUE]);
		else
			MobileFrames_Reset(UIDROPDOWNMENU_MENU_VALUE);
		end
	end;
	if (getglobal(UIDROPDOWNMENU_MENU_VALUE)) and (not getglobal(UIDROPDOWNMENU_MENU_VALUE):IsUserPlaced()) then
		info.disabled = 1;
	end
	UIDropDownMenu_AddButton(info, 1);
	
	--Reset All
	local info = {};
	info.text = RESET_ALL;
	info.value = "ResetAll";
	info.func = function() MobileFrames_Reset("") end;
	--info.notClickable = 1;
	UIDropDownMenu_AddButton(info, 1);
	
	MobileFramesDropDown_Reposition(getglobal("DropDownList"..UIDROPDOWNMENU_MENU_LEVEL), this:GetName());
end

function MobileFramesDropDown_OnLoad()
	UIDropDownMenu_Initialize(this, MobileFramesDropDown_LoadDropDownMenu, "MENU");
end

function MobileFramesDropDown_Reposition(listFrame, anchorName)
	local customPoint = "TOPLEFT";   --Default Anchor
	local offscreenY, offscreenX, anchorPoint, relativePoint, offsetX, offsetY;
	-- Determine whether the menu is off the screen or not
	local offscreenY, offscreenX;
	--Hack for built in bug
	if ( not listFrame:GetRight() ) then
		return;
	end
	
	if ( listFrame:GetBottom() < WorldFrame:GetBottom() ) then
		offscreenY = 1;
	end
	if ( listFrame:GetRight() > WorldFrame:GetRight() ) then
		offscreenX = 1;
	end
	
	local anchorPoint, relativePoint, offsetX, offsetY;
	if ( offscreenY == 1 ) then
		if ( offscreenX == 1 ) then
			anchorPoint = string.gsub(customPoint, "TOP(.*)", "BOTTOM%1");
			anchorPoint = string.gsub(anchorPoint, "(.*)LEFT", "%1RIGHT");
			relativePoint = "TOPRIGHT";
			offsetX = 0;
			offsetY = 14;
		else
			anchorPoint = string.gsub(customPoint, "TOP(.*)", "BOTTOM%1");
			relativePoint = "TOPLEFT";
			offsetX = 0;
			offsetY = 14;
		end
	else
		if ( offscreenX == 1 ) then
			anchorPoint = string.gsub(customPoint, "(.*)LEFT", "%1RIGHT");
			relativePoint = "BOTTOMRIGHT";
			offsetX = 0;
			offsetY = -14;
		else
			anchorPoint = customPoint;
			relativePoint = "BOTTOMLEFT";
			offsetX = 0;
			offsetY = -14;
		end
	end
	listFrame:ClearAllPoints();
	listFrame:SetPoint(anchorPoint, anchorName, relativePoint, offsetX, offsetY);
	
	-- Reshow the "MENU" border
	if (getglobal(listFrame:GetName().."Backdrop")) and (getglobal(listFrame:GetName().."MenuBackdrop")) then
		getglobal(listFrame:GetName().."Backdrop"):Hide();
		getglobal(listFrame:GetName().."MenuBackdrop"):Show();
	end
	--getglobal(listFrame:GetName().."Backdrop"):Show();
	--getglobal(listFrame:GetName().."MenuBackdrop"):Hide();
end

-- <= == == == == == == == == == == == == =>
-- => Mobile WorldStateAlwaysUpFrame
-- <= == == == == == == == == == == == == =>

function MobileFrames_WorldStateAlwaysUpFrameReset()
	WorldStateAlwaysUpFrame.isReset = true;
	WorldStateAlwaysUpFrame:SetUserPlaced(false);
	WorldStateAlwaysUpFrame:ClearAllPoints();
	WorldStateAlwaysUpFrame:SetPoint("TOP", "UIParent", "TOP", -5, -15);
end

-- <= == == == == == == == == == == == =>
-- => Optional Sea duplicates (Don't waste memory if they already exists)
-- <= == == == == == == == == == == == =>

if (Sea and Sea.table and Sea.table.getKeyList) then
	MobileFrames_GetTableKeyList = Sea.table.getKeyList;
else
	MobileFrames_GetTableKeyList = function (passedTable)
		if( type(passedTable) ~= "table" ) then
			return nil;
		end
		
		local keyList = { };
		for key, value in pairs(passedTable) do
			table.insert(keyList, key)
		end
		return keyList;	
	end
end

