--
-- AutoBarProfile
-- Copyright 2006+ Toadkiller of Proudmoore.
--
-- Profile System for AutoBar
-- http://www.wowace.com/wiki/AutoBar
-- http://www.curse-gaming.com/en/wow/addons-4430-1-autobar-toadkiller.html
--

-- Data Structure Example for Toadkiller:
--		AutoBar = {
--			buttons = {AutoBarProfile.basic + AutoBarProfile.<CLASS> + AutoBar_Config["_SHARED1"].buttons + AutoBar_Config["Toadkiller - Proudmoore"].buttons},
--			display = {AutoBar_Config["Toadkiller - Proudmoore"].display or AutoBar_Config["_SHARED1"].display},
--		};
--		AutoBar_Config["Toadkiller - Proudmoore"] = {
--			buttons = {AutoBarProfile.basic + AutoBarProfile.<CLASS> + AutoBar_Config["_SHARED1"].buttons},
--			display = {},
--			profile = {},
--		};
--		AutoBar_Config["_SHARED1"] = {
--			buttons = {},
--			display = {},
--		};
--		AutoBar_Config["_DRUID"] = {
--			buttons = {AutoBarProfile.DRUID},
--			display = {},
--		};
--		AutoBar_Config["_BASIC"] = {
--			buttons = {AutoBarProfile.basic},
--			display = {},
--		};
--		AutoBarProfile.<CLASS>
--		AutoBarProfile.basic

AutoBarProfile = {};
AutoBarProfile.MAX_SHARED_PROFILES = 4;

local HEALSLOT = 4;
local POTIONSLOT = 5;
local BUFFSLOT1 = 7;
local BUFFSLOT2 = 8;
local FOODSLOT = 9;
local FOODSLOT2 = 10;
local BUFFSLOT = 12;
local PETFOOD = 24;
local MOUNTSLOT = 2;

local L = AceLibrary("AceLocale-2.2"):new("AutoBar");
local BS = AceLibrary:GetInstance("Babble-Spell-2.2");

-- Set up Basic Defaults
function AutoBarProfile.InitializeBasic()
	AutoBarProfile.basic = {};
	AutoBarProfile.basic[1] = { "HEARTHSTONE" };

	AutoBarProfile.basic[MOUNTSLOT] = { "MOUNTS", "MOUNTS_FLYING", "MOUNTS_QIRAJI" };
	AutoBarProfile.basic[MOUNTSLOT].arrangeOnUse = true;

	AutoBarProfile.basic[3] = { "BANDAGES", "ALTERAC_BANDAGES", "WARSONG_BANDAGES", "ARATHI_BANDAGES", "UNGORO_RESTORE" };
	AutoBarProfile.basic[HEALSLOT] = { "HEALPOTIONS", "REJUVENATION_POTIONS", "WHIPPER_ROOT", "NIGHT_DRAGONS_BREATH", "PVP_HEALPOTIONS", "ALTERAC_HEAL", "HEALTHSTONE" };
	AutoBarProfile.basic[POTIONSLOT] = {};

	AutoBarProfile.basic[6] = { "PROTECTION_ARCANE", "PROTECTION_FROST", "PROTECTION_NATURE", "PROTECTION_SHADOW", "PROTECTION_FIRE", "PROTECTION_SPELLS" };
	AutoBarProfile.basic[6].arrangeOnUse = true;

	AutoBarProfile.basic[7] = {};
	AutoBarProfile.basic[8] = {};
	AutoBarProfile.basic[9] = {};
	AutoBarProfile.basic[FOODSLOT2] = { "FOOD_PERCENT", "FOOD", "FOOD_CONJURED" };
	AutoBarProfile.basic[11] = { "FOOD_PERCENT_COMBO", "FOOD_COMBO", "FOOD_ARATHI", "FOOD_WARSONG" };
	AutoBarProfile.basic[12] = {};
	AutoBarProfile.basic[13] = { "SHARPENINGSTONES" };
	AutoBarProfile.basic[14] = { "WEIGHTSTONE" };
	AutoBarProfile.basic[15] = { "SWIFTNESSPOTIONS" };
	AutoBarProfile.basic[16] = { "ACTION_POTIONS" };
	AutoBarProfile.basic[17] = { "EXPLOSIVES" };
	AutoBarProfile.basic[18] = { "FISHING_LURES", "FISHING_GEAR", "FISHING_POLES" };
	AutoBarProfile.basic[19] = { "HOURGLASS_SAND", "BATTLE_STANDARD", "BATTLE_STANDARD_AV" };
	AutoBarProfile.basic[20] = { "MINI_PET", "MINI_PET_HOLIDAY" };
	AutoBarProfile.basic[21] = {};
	AutoBarProfile.basic[22] = {};
	AutoBarProfile.basic[23] = {};
	AutoBarProfile.basic[24] = { "QUEST_ITEMS" };

end


-- Set up Class Defaults
function AutoBarProfile.InitializeClass()
	AutoBarProfile.ROGUE = {};
	AutoBarProfile.ROGUE[POTIONSLOT] = { "ENERGYPOTIONS" };
	AutoBarProfile.ROGUE[FOODSLOT] = { "FOOD_WELL_FED", "FOOD_STRENGTH", "FOOD_AGILITY", "FOOD_STAMINA", "FOOD_SPIRIT", "FOOD_HPREGEN", "FOOD_PERCENT_BONUS", "FOOD_OTHER" };
	AutoBarProfile.ROGUE[20] = { "POISON-MINDNUMBING" };
	AutoBarProfile.ROGUE[21] = { "POISON-WOUND" };
	AutoBarProfile.ROGUE[22] = { "POISON-CRIPPLING" };
	AutoBarProfile.ROGUE[23] = { "POISON-DEADLY" };
	AutoBarProfile.ROGUE[24] = { "POISON-INSTANT" };
	AutoBarProfile.ROGUE[BUFFSLOT] = { "SCROLL_AGILITY", "SCROLL_PROTECTION", "SCROLL_SPIRIT", "SCROLL_STAMINA", "SCROLL_STRENGTH", "BUFF_ATTACKPOWER", "BUFF_ATTACKSPEED", "BUFF_DODGE", "BUFF_FROST", "BUFF_FIRE", "SCROLL_INTELLECT" };

	AutoBarProfile.WARRIOR = {};
	AutoBarProfile.WARRIOR[POTIONSLOT] = { "RAGEPOTIONS" };
	AutoBarProfile.WARRIOR[FOODSLOT] = AutoBarProfile.ROGUE[FOODSLOT];
	AutoBarProfile.WARRIOR[BUFFSLOT] = AutoBarProfile.ROGUE[BUFFSLOT];

	AutoBarProfile.DRUID = {};
	AutoBarProfile.DRUID[POTIONSLOT] = { "RUNES", "MANAPOTIONS", "REJUVENATION_POTIONS", "NIGHT_DRAGONS_BREATH", "PVP_MANAPOTIONS", "ALTERAC_MANA" };
	AutoBarProfile.DRUID[BUFFSLOT1] = { "WATER", "WATER_PERCENT", "WATER_CONJURED" };
	AutoBarProfile.DRUID[BUFFSLOT2] = { "WATER_SPIRIT" };
	AutoBarProfile.DRUID[FOODSLOT] = { "FOOD_WELL_FED", "FOOD_STRENGTH", "FOOD_AGILITY", "FOOD_STAMINA", "FOOD_INTELLECT", "FOOD_SPIRIT", "FOOD_HPREGEN", "FOOD_MANAREGEN", "FOOD_PERCENT_BONUS", "FOOD_OTHER" };
	AutoBarProfile.DRUID[BUFFSLOT] = AutoBarProfile.ROGUE[BUFFSLOT];

	AutoBarProfile.HUNTER = {};
	AutoBarProfile.HUNTER[POTIONSLOT] = AutoBarProfile.DRUID[POTIONSLOT];
	AutoBarProfile.HUNTER[BUFFSLOT1] = AutoBarProfile.DRUID[BUFFSLOT1];
	AutoBarProfile.HUNTER[BUFFSLOT2] = AutoBarProfile.DRUID[BUFFSLOT2];
	AutoBarProfile.HUNTER[FOODSLOT] = AutoBarProfile.DRUID[FOODSLOT];
	AutoBarProfile.HUNTER[PETFOOD] = { "FOOD_PET_BREAD", "FOOD_PET_CHEESE", "FOOD_PET_FISH", "FOOD_PET_FRUIT", "FOOD_PET_FUNGUS", "FOOD_PET_MEAT" };
	AutoBarProfile.HUNTER[PETFOOD].arrangeOnUse = true;
	AutoBarProfile.HUNTER[PETFOOD].rightClickTargetsPet = true;
	AutoBarProfile.HUNTER[BUFFSLOT] = AutoBarProfile.ROGUE[BUFFSLOT];

	AutoBarProfile.MAGE = {};
	AutoBarProfile.MAGE[POTIONSLOT] = { "RUNES", "MANAPOTIONS", "REJUVENATION_POTIONS", "NIGHT_DRAGONS_BREATH", "PVP_MANAPOTIONS", "ALTERAC_MANA", "MANASTONE" };
	AutoBarProfile.MAGE[BUFFSLOT1] = AutoBarProfile.DRUID[BUFFSLOT1];
	AutoBarProfile.MAGE[BUFFSLOT2] = AutoBarProfile.DRUID[BUFFSLOT2];
	AutoBarProfile.MAGE[FOODSLOT] = { "FOOD_WELL_FED", "FOOD_STAMINA", "FOOD_INTELLECT", "FOOD_HPREGEN", "FOOD_MANAREGEN" };
	AutoBarProfile.MAGE[BUFFSLOT] = { "SCROLL_AGILITY", "SCROLL_PROTECTION", "SCROLL_SPIRIT", "SCROLL_STAMINA", "SCROLL_STRENGTH", "BUFF_ATTACKPOWER", "BUFF_ATTACKSPEED", "SCROLL_INTELLECT" };

	AutoBarProfile.PALADIN = {};
	AutoBarProfile.PALADIN[POTIONSLOT] = AutoBarProfile.DRUID[POTIONSLOT];
	AutoBarProfile.PALADIN[BUFFSLOT1] = AutoBarProfile.DRUID[BUFFSLOT1];
	AutoBarProfile.PALADIN[BUFFSLOT2] = AutoBarProfile.DRUID[BUFFSLOT2];
	AutoBarProfile.PALADIN[FOODSLOT] = AutoBarProfile.DRUID[FOODSLOT];
	AutoBarProfile.PALADIN[BUFFSLOT] = AutoBarProfile.DRUID[BUFFSLOT];

	AutoBarProfile.PRIEST = {};
	AutoBarProfile.PRIEST[POTIONSLOT] = AutoBarProfile.DRUID[POTIONSLOT];
	AutoBarProfile.PRIEST[BUFFSLOT1] = AutoBarProfile.DRUID[BUFFSLOT1];
	AutoBarProfile.PRIEST[BUFFSLOT2] = AutoBarProfile.DRUID[BUFFSLOT2];
	AutoBarProfile.PRIEST[FOODSLOT] = AutoBarProfile.MAGE[FOODSLOT];
	AutoBarProfile.PRIEST[BUFFSLOT] = AutoBarProfile.MAGE[BUFFSLOT];

	AutoBarProfile.SHAMAN = {};
	AutoBarProfile.SHAMAN[POTIONSLOT] = AutoBarProfile.DRUID[POTIONSLOT];
	AutoBarProfile.SHAMAN[BUFFSLOT1] = AutoBarProfile.DRUID[BUFFSLOT1];
	AutoBarProfile.SHAMAN[BUFFSLOT2] = AutoBarProfile.DRUID[BUFFSLOT2];
	AutoBarProfile.SHAMAN[FOODSLOT] = AutoBarProfile.DRUID[FOODSLOT];
	AutoBarProfile.SHAMAN[BUFFSLOT] = AutoBarProfile.DRUID[BUFFSLOT];

	AutoBarProfile.WARLOCK = {};
	AutoBarProfile.WARLOCK[POTIONSLOT] = AutoBarProfile.DRUID[POTIONSLOT];
	AutoBarProfile.WARLOCK[BUFFSLOT1] = AutoBarProfile.DRUID[BUFFSLOT1];
	AutoBarProfile.WARLOCK[BUFFSLOT2] = AutoBarProfile.DRUID[BUFFSLOT2];
	AutoBarProfile.WARLOCK[FOODSLOT] = AutoBarProfile.MAGE[FOODSLOT];
	AutoBarProfile.WARLOCK[BUFFSLOT] = AutoBarProfile.MAGE[BUFFSLOT];

	for buttonIndex = 1, AUTOBAR_MAXBUTTONS, 1 do
		if (not AutoBarProfile[AutoBarProfile.CLASS][buttonIndex]) then
			AutoBarProfile[AutoBarProfile.CLASS][buttonIndex] = {};
		end
	end
	AutoBarProfile[AutoBarProfile.CLASS][FOODSLOT].arrangeOnUse = true;


end


local function clone(o)
	local new_o = {};	-- creates a new object
	for i, v in pairs(o) do
		if (type(v) == "table") then
			new_o[i] = clone(v);			-- store them in new table
		else
			new_o[i] = v;				-- store them in new table
		end
	end
--
--	-- TODO: This is goddamn stupid.  Replace / revisit this in 2.0
--	if (table.maxn(new_o) ~= table.maxn(o)) then
--		DEFAULT_CHAT_FRAME:AddMessage("clone bad maxn behaviour ");
--		DEFAULT_CHAT_FRAME:AddMessage("clone bad maxn behaviour " .. nil);
--	end
--
	return new_o;
end


-- Clone the given profile, returning the clone
function AutoBarProfile.CloneUserProfile()
	if (AutoBarProfile:GetProfile()) then
		return clone(AutoBarProfile:GetProfile());
	else
		return nil;
	end
end


-- Clone the given profile, returning the clone
function AutoBarProfile.CloneProfile(profileName)
	if (AutoBar_Config[profileName]) then
		return clone(AutoBar_Config[profileName]);
	else
		return nil;
	end
end


-- Clone all profiles, return them in a table
function AutoBarProfile.CloneProfiles()
	local profilesClone = {};
	profilesClone[AutoBar.currentPlayer] = AutoBarProfile.CloneProfile(AutoBar.currentPlayer);
	for index = 1, AutoBarProfile.MAX_SHARED_PROFILES, 1 do
		local sharedName = "_SHARED"..index;
		profilesClone[sharedName] = AutoBarProfile.CloneProfile(sharedName);
	end
	if (AutoBar_Config[AutoBarProfile.CLASSPROFILE]) then
		profilesClone[AutoBarProfile.CLASSPROFILE] = AutoBarProfile.CloneProfile(AutoBarProfile.CLASSPROFILE);
	end
	if (AutoBar_Config["_BASIC"]) then
		profilesClone["_BASIC"] = AutoBarProfile.CloneProfile("_BASIC");
	end
	return profilesClone;
end


-- Revert all profiles from the cloned table
function AutoBarProfile.RevertProfiles(profilesClone)
	AutoBar_Config[AutoBar.currentPlayer] = profilesClone[AutoBar.currentPlayer];
	for index = 1, AutoBarProfile.MAX_SHARED_PROFILES, 1 do
		local sharedName = "_SHARED"..index;
		AutoBar_Config[sharedName] = profilesClone[sharedName];
	end
	if (profilesClone[AutoBarProfile.CLASSPROFILE]) then
		AutoBar_Config[AutoBarProfile.CLASSPROFILE] = profilesClone[AutoBarProfile.CLASSPROFILE];
	end
	if (profilesClone["_BASIC"]) then
		AutoBar_Config["_BASIC"] = profilesClone["_BASIC"];
	end
end


-- Set up space by profileName
function AutoBarProfile.InitializeProfile(profileName)
	if (not AutoBar_Config[profileName]) then
		AutoBar_Config[profileName] = {};
	end
	if (not AutoBar_Config[profileName].buttons) then
		AutoBar_Config[profileName].buttons = {};
	end
	if (not AutoBar_Config[profileName].display) then
		AutoBar_Config[profileName].display = {};
	end

	local display = AutoBar_Config[profileName].display;
	if (not display.rows) then
		display.rows = 1;
	end
	if (not display.columns) then
		display.columns = AUTOBAR_MAXBUTTONS;
	end
	if (not display.gapping) then
		display.gapping = 0;
	end
	if (not display.alpha) then
		display.alpha = 10;
	end
	if (not display.buttonWidth) then
		display.buttonWidth = 36;
	end
	if (not display.buttonHeight) then
		display.buttonHeight = 36;
	end
	if (not display.dockShiftX) then
		display.dockShiftX = 0;
	end
	if (not display.dockShiftY) then
		display.dockShiftY = 0;
	end
	if (not (display.popupToTop or display.popupToLeft or display.popupToRight or display.popupToBottom)) then
		display.popupToTop = true;
	end
	if (not display.style) then
		display.style = 3;
	end
end



function AutoBarProfile:CanCastSpell(spellName)
	usable, noMana = IsUsableSpell(spellName)
	if (not usable) then
		if (not nomana) then
			return false;
		else
			return true;
		end
	end
	return true;
end


-- Spell specific inits
function AutoBarProfile.InitializeSpells()
	local castList, castSpell;
	for i, category in pairs(AutoBar_Category_Info) do
		castList = category.castList;
		if (castList) then
			for index = 1, table.maxn(castList), 2 do
				if (AutoBarProfile.CLASS == castList[index]) then
					castSpell = castList[index + 1];
					if (castSpell and AutoBarProfile:CanCastSpell(castSpell)) then	-- TODO: update on leveling in case new spell aquired
						category.castSpell = castSpell;
						break;
					end
				end
			end
		end
	end

	if (AutoBarProfile.CLASS == "DRUID") then
		AutoBarProfile.basic[MOUNTSLOT].castSpell = BS["Travel Form"];
	elseif (AutoBarProfile.CLASS == "MAGE") then
		AutoBarProfile.MAGE[BUFFSLOT1].castSpell = BS["Conjure Water"];
		AutoBarProfile.MAGE[FOODSLOT2].castSpell = BS["Conjure Food"];
		if (AutoBarProfile:CanCastSpell("Conjure Mana Ruby")) then
			AutoBarProfile.MAGE[POTIONSLOT].castSpell = BS["Conjure Mana Ruby"];
		elseif (AutoBarProfile:CanCastSpell("Conjure Mana Ruby")) then
			AutoBarProfile.MAGE[POTIONSLOT].castSpell = BS["Conjure Mana Jade"];
		elseif (AutoBarProfile:CanCastSpell("Conjure Mana Ruby")) then
			AutoBarProfile.MAGE[POTIONSLOT].castSpell = BS["Conjure Mana Citrine"];
		elseif (AutoBarProfile:CanCastSpell("Conjure Mana Ruby")) then
			AutoBarProfile.MAGE[POTIONSLOT].castSpell = BS["Conjure Mana Agate"];
		end
	elseif (AutoBarProfile.CLASS == "PALADIN") then
		if (AutoBarProfile:CanCastSpell("Summon Charger")) then
			AutoBarProfile.basic[MOUNTSLOT].castSpell = BS["Summon Charger"];
		elseif (AutoBarProfile:CanCastSpell("Summon Warhorse")) then
			AutoBarProfile.MAGE[MOUNTSLOT].castSpell = BS["Summon Warhorse"];
		end
	elseif (AutoBarProfile.CLASS == "SHAMAN") then
		AutoBarProfile.basic[MOUNTSLOT].castSpell = BS["Ghost Wolf"];
	elseif (AutoBarProfile.CLASS == "WARLOCK") then
		if (AutoBarProfile:CanCastSpell("Summon Dreadsteed")) then
			AutoBarProfile.basic[MOUNTSLOT].castSpell = BS["Summon Dreadsteed"];
		elseif (AutoBarProfile:CanCastSpell("Summon Felsteed")) then
			AutoBarProfile.MAGE[MOUNTSLOT].castSpell = BS["Summon Felsteed"];
		end
		AutoBarProfile.basic[HEALSLOT].castSpell = BS["Create Healthstone"];
	end
end


-- Convert all slots to use tables and not single items
function AutoBarProfile.ConvertSlots(profileName)
	if (not AutoBar_Config[profileName]) then
		return;
	end
	if (not AutoBar_Config[profileName].buttons) then
		return;
	end
	local temp;
	local buttons = AutoBar_Config[profileName].buttons;
	for buttonIndex = 1, AUTOBAR_MAXBUTTONS, 1 do
		if (buttons[buttonIndex] and type(buttons[buttonIndex]) ~= "table") then
			temp = buttons[buttonIndex];
			buttons[buttonIndex] = { temp };
		elseif (not buttons[buttonIndex]) then
			buttons[buttonIndex] = {};
		end

		local categoryMap = {
			["FISHINGITEMS"] = "FISHING_LURES",
			["FOOD_INTELLIGENCE"] = "FOOD_INTELLECT",
			["FOOD_WATER"] = "FOOD_COMBO",
			["MOUNTS_TROLL"] = "MOUNTS",
			["MOUNTS_ORC"] = "MOUNTS",
			["MOUNTS_UNDEAD"] = "MOUNTS",
			["MOUNTS_TAUREN"] = "MOUNTS",
			["MOUNTS_HUMAN"] = "MOUNTS",
			["MOUNTS_NIGHTELF"] = "MOUNTS",
			["MOUNTS_DWARF"] = "MOUNTS",
			["MOUNTS_GNOME"] = "MOUNTS",
			["PVP_HEALPOTIONS"] = "AAACLEAR",
			["PVP_MANAPOTIONS"] = "AAACLEAR",
			["WEIGHTSTONE"] = "WEIGHTSTONES",
			["MANA_OIL"] = "OIL_MANA",
			["WIZARD_OIL"] = "OIL_WIZARD",
		};
		local slotInfo = buttons[buttonIndex];
		for i = 1, table.maxn(slotInfo), 1 do
			if (categoryMap[slotInfo[i]]) then
				slotInfo[i] = categoryMap[slotInfo[i]];
			end
		end

		-- Delete all adjacent duplicates (mostly mounts + the occasional user error)
		local i = 2;
		while (slotInfo[i]) do
			if (slotInfo[i] == slotInfo[i - 1]) then
				table.remove(slotInfo, i);
			else
				i = i + 1;
			end
		end
	end
end


-- Convert all profile's slots to use tables and not single items
-- Map obsolete categories to new ones
function AutoBarProfile:Upgrade()
	AutoBarProfile.ConvertSlots(AutoBar.currentPlayer);
	AutoBarProfile.ConvertSlots("_SHARED1");
	AutoBarProfile.ConvertSlots("_SHARED2");
	AutoBarProfile.ConvertSlots("_SHARED3");
	AutoBarProfile.ConvertSlots("_SHARED4");
	AutoBarProfile.ConvertSlots(AutoBarProfile.CLASSPROFILE);
	AutoBarProfile.ConvertSlots("_BASIC");

	upgraded = true;
end


local upgraded = false;
-- Set up defaults for the player if required
function AutoBarProfile.Initialize()
	if (not AutoBar_Config) then AutoBar_Config = {}; end

	if (not AutoBarProfile.CLASS) then
		_, AutoBarProfile.CLASS = UnitClass("player");
		AutoBarProfile.CLASSPROFILE = "_" .. AutoBarProfile.CLASS;
	end

	if (not upgraded) then
		AutoBarProfile.Upgrade();
	end

	if (not AutoBarProfile[AutoBarProfile.CLASS]) then
		AutoBarProfile.InitializeClass();
	end

	if (not AutoBarProfile.basic) then
		AutoBarProfile.InitializeBasic();
	end

	AutoBarProfile.InitializeSpells();

	AutoBarProfile.InitializeProfile(AutoBar.currentPlayer);
	for index = 1, AutoBarProfile.MAX_SHARED_PROFILES, 1 do
		local sharedName = "_SHARED"..index;
		AutoBarProfile.InitializeProfile(sharedName);
	end
	if (not AutoBar_Config[AutoBarProfile.CLASSPROFILE]) then
		AutoBarProfile.InitializeProfile(AutoBarProfile.CLASSPROFILE);
		AutoBar_Config[AutoBarProfile.CLASSPROFILE].buttons = clone(AutoBarProfile[AutoBarProfile.CLASS]);
	end
	if (not AutoBar_Config[AutoBarProfile.CLASSPROFILE].buttons) then
		AutoBar_Config[AutoBarProfile.CLASSPROFILE].buttons = clone(AutoBarProfile[AutoBarProfile.CLASS]);
	end
	if (not AutoBar_Config["_BASIC"]) then
		AutoBarProfile.InitializeProfile("_BASIC");
		AutoBar_Config["_BASIC"].buttons = clone(AutoBarProfile.basic);
	end
	if (not AutoBar_Config["_BASIC"].buttons) then
		AutoBar_Config["_BASIC"].buttons = clone(AutoBarProfile.basic);
	end

	if (not AutoBarProfile:GetProfile()) then
		AutoBarProfile:SetDefaults();
	end
	local profile = AutoBarProfile:GetProfile();
	if (not profile.shared) then
		profile.shared = "_SHARED1";
	end
	if (profile.layout == 1) then
		profile.layoutProfile = AutoBar.currentPlayer;
	elseif (profile.layout == 2) then
		profile.layoutProfile = profile.shared;
	else
		profile.layout = 2;
		profile.layoutProfile = profile.shared;
	end
	if (not AutoBar.buttons) then
		AutoBarProfile:ButtonsCopy();
	end

	AutoBarProfile:DisplayCopy();
end


function AutoBarProfile:SetDefaults()
	if (not AutoBarProfile:GetProfile()) then
		AutoBar_Config[AutoBar.currentPlayer].profile = {};
	end
	if (AutoBar_Config[AutoBar.currentPlayer].buttons and table.maxn(AutoBar_Config[AutoBar.currentPlayer].buttons) > 0) then
		AutoBarProfile:SetDefaultsSingle();
	else
		AutoBarProfile:SetDefaultsStandard();
	end
end


function AutoBarProfile:SetDefaultsSingle()
	local profile = AutoBarProfile:GetProfile();
	profile.useCharacter = true;
	profile.useShared = false;
	profile.useClass = false;
	profile.useBasic = false;
	profile.edit = 1;
	profile.shared = "_SHARED1";
	profile.layout = 1;
	profile.layoutProfile = AutoBar.currentPlayer;
	profile.style = 3;
end


function AutoBarProfile:SetDefaultsShared()
	local profile = AutoBarProfile:GetProfile();
	profile.useCharacter = true;
	profile.useShared = true;
	profile.useClass = false;
	profile.useBasic = false;
	profile.edit = 2;
	profile.shared = "_SHARED1";
	profile.layout = 2;
	profile.layoutProfile = "_SHARED1";
	profile.style = 3;
end


function AutoBarProfile:SetDefaultsStandard()
	local profile = AutoBarProfile:GetProfile();
	profile.useCharacter = true;
	profile.useShared = true;
	profile.useClass = true;
	profile.useBasic = true;
	profile.edit = 2;
	profile.shared = "_SHARED1";
	profile.layout = 2;
	profile.layoutProfile = "_SHARED1";
	profile.style = 3;
end


function AutoBarProfile:SetDefaultsBlankSlate()
	local profile = AutoBarProfile:GetProfile();
	profile.useCharacter = true;
	profile.useShared = true;
	profile.useClass = false;
	profile.useBasic = false;
	profile.edit = 2;
	profile.shared = "_SHARED1";
	profile.layout = 2;
	profile.layoutProfile = "_SHARED1";
	profile.style = 3;
end


function AutoBarProfile:GetEditPlayer()
	local editPlayer;
	local profile = AutoBarProfile:GetProfile();
	if (profile.edit == 1) then
		editPlayer = AutoBar.currentPlayer;
	elseif (profile.edit == 2) then
		editPlayer = profile.shared;
	elseif (profile.edit == 3) then
		editPlayer = AutoBarProfile.CLASSPROFILE;
	elseif (profile.edit == 4) then
		editPlayer = "_BASIC";
	else
		profile.edit = 1;
		editPlayer = AutoBar.currentPlayer;
	end
	return editPlayer;
end


function AutoBarProfile:ProfileEditingChanged()
	AutoBarConfig.editPlayer = AutoBarProfile:GetEditPlayer();
	AutoBarProfile.Initialize();
	AutoBarProfile:ButtonsCopy();
	AutoBarConfig.OnShow();
	AutoBar.ConfigChanged();
end


function AutoBarProfile:GetProfile()
	return AutoBar_Config[AutoBar.currentPlayer].profile;
end


function AutoBarProfile:InitializeLayoutProfile()
	local profile = AutoBarProfile:GetProfile();
	if (profile.layout == 1) then
		profile.layoutProfile = AutoBar.currentPlayer;
	else
		profile.layoutProfile = profile.shared;
	end
end


function AutoBarProfile:LayoutChanged()
	AutoBarProfile:InitializeLayoutProfile();
	AutoBarProfile:ProfileChanged();
end


function AutoBarProfile:ProfileChanged()
	AutoBarProfile:DisplayCopy();
	AutoBarProfile:ButtonsCopy();
	AutoBarConfig.OnShow();
	AutoBar.ConfigChanged();
end


function AutoBarProfile:DisplayChanged()
	AutoBarProfile:DisplayCopy();
	AutoBar.ConfigChanged();
end


function AutoBarProfile:ButtonsChanged()
--/script DEFAULT_CHAT_FRAME:AddMessage(AutoBarProfile:GetProfile().shared);
	AutoBarProfile:ButtonsCopy();
	AutoBar.ConfigChanged();
	AutoBar:LayoutUpdate();
	AutoBarConfig:SlotsViewInitialize();
	AutoBarConfig:SlotsInitialize();
end


function AutoBarProfile:DisplayCopy()
	local profile = AutoBarProfile:GetProfile();

	AutoBar.display = nil;
	if (profile.layout == 1) then
		AutoBar.display = AutoBar_Config[AutoBar.currentPlayer].display;
	else
		AutoBar.display = AutoBar_Config[profile.shared].display;
	end
end


-- Assign buttons from eligible layer with precedence characterButtons > sharedButtons > classButtons > basicButtons
function AutoBarProfile:ButtonsCopy()
	local profile = AutoBarProfile:GetProfile();
	local characterButtons, sharedButtons, classButtons, basicButtons;

	if (profile.useCharacter and AutoBar_Config[AutoBar.currentPlayer].buttons) then
		characterButtons = AutoBar_Config[AutoBar.currentPlayer].buttons;
	end
	if (profile.useShared and profile.shared and AutoBar_Config[profile.shared] and AutoBar_Config[profile.shared].buttons) then
		sharedButtons = AutoBar_Config[profile.shared].buttons;
	end
	if (profile.useClass and AutoBar_Config[AutoBarProfile.CLASSPROFILE] and AutoBar_Config[AutoBarProfile.CLASSPROFILE].buttons) then
		classButtons = AutoBar_Config[AutoBarProfile.CLASSPROFILE].buttons;
	end
	if (profile.useBasic and AutoBar_Config["_BASIC"] and AutoBar_Config["_BASIC"].buttons) then
		basicButtons = AutoBar_Config["_BASIC"].buttons;
	end

	-- Copy the buttons
	if (not AutoBar.buttons) then
		AutoBar.buttons = {};
	end
	for buttonIndex = 1, AUTOBAR_MAXBUTTONS, 1 do
		AutoBar.buttons[buttonIndex] = nil;
		if (characterButtons and characterButtons[buttonIndex] and characterButtons[buttonIndex][1]) then
			AutoBar.buttons[buttonIndex] = clone(characterButtons[buttonIndex]);
		elseif (sharedButtons and sharedButtons[buttonIndex] and sharedButtons[buttonIndex][1]) then
			AutoBar.buttons[buttonIndex] = clone(sharedButtons[buttonIndex]);
		elseif (classButtons and classButtons[buttonIndex] and classButtons[buttonIndex][1]) then
			AutoBar.buttons[buttonIndex] = clone(classButtons[buttonIndex]);
		elseif (basicButtons and basicButtons[buttonIndex] and basicButtons[buttonIndex][1]) then
			AutoBar.buttons[buttonIndex] = clone(basicButtons[buttonIndex]);
		else
			AutoBar.buttons[buttonIndex] = {};
		end
	end
end


-- Assign buttons from classButtons and basicButtons layer to characterButtons
function AutoBarProfile:ButtonsCopySingle()
	local profile = AutoBarProfile:GetProfile();
	local characterButtons, classButtons, basicButtons;

	characterButtons = AutoBar_Config[AutoBar.currentPlayer].buttons;
	classButtons = AutoBarProfile[AutoBarProfile.CLASS];
	basicButtons = AutoBarProfile.basic;

	-- Copy the buttons
	for buttonIndex = 1, AUTOBAR_MAXBUTTONS, 1 do
		characterButtons[buttonIndex] = nil;
		if (classButtons and classButtons[buttonIndex] and classButtons[buttonIndex][1]) then
			characterButtons[buttonIndex] = clone(classButtons[buttonIndex]);
		elseif (basicButtons and basicButtons[buttonIndex] and basicButtons[buttonIndex][1]) then
			characterButtons[buttonIndex] = clone(basicButtons[buttonIndex]);
		else
			characterButtons[buttonIndex] = {};
		end
	end
end


-- Assign buttons from classButtons and basicButtons layers to characterButtons and sharedButtons respectively
function AutoBarProfile:ButtonsCopyShared()
	local profile = AutoBarProfile:GetProfile();
	local characterButtons, sharedButtons, classButtons, basicButtons;

	characterButtons = AutoBar_Config[AutoBar.currentPlayer].buttons;
	sharedButtons = AutoBar_Config[profile.shared].buttons;
	classButtons = AutoBarProfile[AutoBarProfile.CLASS];
	basicButtons = AutoBarProfile.basic;

	-- Copy the buttons
	for buttonIndex = 1, AUTOBAR_MAXBUTTONS, 1 do
		characterButtons[buttonIndex] = nil;
		if (classButtons and classButtons[buttonIndex] and classButtons[buttonIndex][1]) then
			characterButtons[buttonIndex] = clone(classButtons[buttonIndex]);
		else
			characterButtons[buttonIndex] = {};
		end
		sharedButtons[buttonIndex] = nil;
		if (basicButtons and basicButtons[buttonIndex] and basicButtons[buttonIndex][1]) then
			sharedButtons[buttonIndex] = clone(basicButtons[buttonIndex]);
		else
			sharedButtons[buttonIndex] = {};
		end
	end
end


-- Reset the defaults and clear out characterButtons and sharedButtons respectively
function AutoBarProfile:ButtonsCopyStandard()
	local profile = AutoBarProfile:GetProfile();
	local characterButtons, sharedButtons, classButtons, basicButtons;
	local classLayerButtons, basicLayerButtons;

	characterButtons = AutoBar_Config[AutoBar.currentPlayer].buttons;
	sharedButtons = AutoBar_Config[profile.shared].buttons;
	classButtons = AutoBarProfile[AutoBarProfile.CLASS];
	basicButtons = AutoBarProfile.basic;
	classLayerButtons = AutoBar_Config[AutoBarProfile.CLASSPROFILE].buttons;
	basicLayerButtons = AutoBar_Config["_BASIC"].buttons;

	-- Copy the buttons
	for buttonIndex = 1, AUTOBAR_MAXBUTTONS, 1 do
		characterButtons[buttonIndex] = {};
		sharedButtons[buttonIndex] = {};
		classLayerButtons[buttonIndex] = nil;
		if (classButtons and classButtons[buttonIndex] and classButtons[buttonIndex][1]) then
			classLayerButtons[buttonIndex] = clone(classButtons[buttonIndex]);
		else
			classLayerButtons[buttonIndex] = {};
		end
		basicLayerButtons[buttonIndex] = nil;
		if (basicButtons and basicButtons[buttonIndex] and basicButtons[buttonIndex][1]) then
			basicLayerButtons[buttonIndex] = clone(basicButtons[buttonIndex]);
		else
			basicLayerButtons[buttonIndex] = {};
		end
	end
end


-- /script DEFAULT_CHAT_FRAME:AddMessage(tostring(AutoBarProfile.basic[2].castSpell))
-- /script DEFAULT_CHAT_FRAME:AddMessage(tostring(AutoBar.buttons[2].castSpell))
