--[[ $Id: Bartender3_BarStates.lua 20364 2006-12-13 13:59:18Z nevcairiel $ ]]

-- stances, indexd by their actual name
Bartender3.DefaultStanceMap = { 
	["WARRIOR"] = {
		{
			name = "Battle Stance",
			short = "battle",
			defpage = 7,
		},
		{
			name = "Defensive Stance",
			short = "def",
			defpage = 8,
		},
		{
			name = "Berserker Stance",
			short = "berserker",
			defpage = 9,
		},
	},
	["DRUID"] = {
		{
			name = "Bear Form",
			short = "bear",
			defpage = 9,
		},
		{
			name = "Aquatic Form",
			short = "aqua",
			hidden = true,
		},
		{
			name = "Cat Form",
			short = "cat",
			defpage = 7,
		},
		{
			name = "Travel Form",
			short = "travel",
			hidden = true,
		},
		{
			name = "Moonkin/Tree of Life",
			short = "moontree",
		},
		{
			name = "Flying Form",
			short = "fly",
			hidden = true,
		},
		{
			name = "Cat Form (Prowl)",
			short = "prowl",
			defpage = 8,
			dummy = true,
		},
	},
	["ROGUE"] = {
		{
			name = "Stealth",
			short = "stealth",
			defpage = 7,
		},
	},
	["PRIEST"] = {
		{
			name = "Shadowform",
			short = "shadowform",
		},
	}
}

local function tfind(haystack, needle)
	for i,v in pairs(haystack) do
		if v == needle then return i end
	end
	return nil
end

function Bartender3:CreateStanceMap()
	local class = Bartender3.playerclass
	local stanceinfo = Bartender3.DefaultStanceMap[class] or {}
	
	self.stancemap = {}
	for i,v in pairs(stanceinfo) do
		tinsert(self.stancemap, {
			["short"] = v.short,
			["name"] = v.name,
			["state"] = i,
			["defpage"] = v.defpage,
			["hidden"] = v.hidden,
		})
	end
end

function Bartender3.Class.ActionBar.prototype:InitStates()
	if not Bartender3.stancemap then Bartender3:CreateStanceMap() end
	local class, frame = Bartender3.playerclass, self.frame
	local stanceinfo = Bartender3.stancemap
	
	-- setup states
	if self.config.States == nil then self.config.States = {} end
	
	-- Setup Stances
	if stanceinfo ~= nil then
		-- stance config is nil and we are bar1, setup default stances.
		if self.config.Stances == nil then self.config.Stances = {} end
		for _,v in pairs(Bartender3.DefaultStanceMap) do 
		-- set default stance page if we are on the mainbar
			if self.mainbar and not v.hidden and self.config.Stances[v.short] == nil and v.defpage then
				self.config.Stances[v.short] = v.defpage
			end
		end
		
		local form = GetShapeshiftForm(true)
		
		if stanceinfo[form] and self.config.StatesEnabled then
			local page
			if class == "DRUID" and stanceinfo[form].short == "cat" and IsStealthed() then 
				page = self.config.Stances["prowl"]
			else
				page = self.config.Stances[stanceinfo[form].short]
			end
			frame:SetAttribute("state", page or 0)
		end
	end
	
	self:UpdateStates()
end

function Bartender3.Class.ActionBar.prototype:UpdateStates()
	if not Bartender3.stancemap then Bartender3:CreateStanceMap() end
	local frame = self.frame
	
	-- init the statebutton with our 10 bars
	for i=0,10 do
		self:AddButtonStates(i, i)
	end
	
	if self.mainbar then
		local transition = ""
		for i=0,10 do
			transition = transition .. format("%s-%s:%s;",2 * 10000 + i * 100, 2 * 10000 + i * 100 + 10, i)
		end
		frame:SetAttribute("statemap-actionbar-1", transition)
		for i=2,6 do
			frame:SetAttribute("statemap-actionbar-"..i, self:CreateManualTransitionMap(i))
		end
	end
	
	self:RefreshStatemap()
end

function Bartender3.Class.ActionBar.prototype:GetStanceState(stance)
	local state = 0
	if type(stance) == "table" then 
		if stance.hidden then 
			state = nil
		else 
			state = self.config.Stances[stance.short]
		end
	else
		state = self.config.Stances[stance]
	end
	if state == 0 or not self.config.StatesEnabled then state = nil end
	return state
end

function Bartender3.Class.ActionBar.prototype:RefreshStatemap()
	local class, frame = Bartender3.playerclass, self.frame
	local states = self.config.StatesEnabled
	
	-- setup statemaps for modifiers
	for _,v in pairs(Bartender3.statemodifiers) do
		local page = self.config.States[v]
		if page == 0 then page = nil end
		if not states or not page then
			frame:SetAttribute("statemap-"..v.."-0", nil)
			frame:SetAttribute("statemap-"..v.."-1", nil)
		else
			local trans1, trans2 = self:CreateModifierTransitionMap(page)
			frame:SetAttribute("statemap-"..v.."-0", trans2)
			frame:SetAttribute("statemap-"..v.."-1", trans1)
		end
	end
	
	-- HUGE class based block for stances -- it looks somewhat weird, try to optimize without breaking sometime
	-- optimized now - somewhat at least
	if Bartender3.stancemap ~= nil then
		frame:SetAttribute("statemap-stance-0", "0")
		for i,v in pairs(Bartender3.stancemap) do
			frame:SetAttribute("statemap-stance-"..i, self:GetStanceState(v))
		end
		if class == "DRUID" then
			-- stealthing options
			if self:GetStanceState("cat") and self:GetStanceState("prowl") then
				frame:SetAttribute("statemap-stealth-0", self:GetStanceState("prowl")..":"..self:GetStanceState("cat"))
				frame:SetAttribute("statemap-stealth-1", self:GetStanceState("cat")..":"..self:GetStanceState("prowl"))
			else
				frame:SetAttribute("statemap-stealth-0", nil)
				frame:SetAttribute("statemap-stealth-1", nil)
			end
		end
	end
	self:ApplyStateButton()
end

function Bartender3.Class.ActionBar.prototype:CreateModifierTransitionMap(target)
	local prefix = 1
	local manprefix = 2
	-- maps[1] is for entering the target -- save the state in the new state
	-- maps[2] is for going back to where we came -- recall state
	local maps = {[1] = "", [2] = ""}
	for i=0,10 do
		local id = prefix * 10000 + i * 100 + target
		self:AddButtonStates(id, target)
		maps[1] = maps[1] .. format("%s:%s;", i, id)
		if self.mainbar then maps[1] = maps[1] .. format("%s-%s:%s;", manprefix * 10000 + i * 100, manprefix * 10000 + i * 100 + 10, id) end
		maps[2] = maps[2] .. format("%s-%s:%s;", id - target, id - target + 10, i)
	end
	return maps[1], maps[2]
end

function Bartender3.Class.ActionBar.prototype:CreateManualTransitionMap(target)
	local prefix = 2
	-- maps[1] is for entering the target -- save the state in the new state
	-- maps[2] is for going back to where we came -- recall state
	local map = ""
	for i=0,10 do
		local id = prefix * 10000 + i * 100 + target
		self:AddButtonStates(id, target)
		map = map .. format("%s:%s;", i, id)
		map = map .. format("%s-%s:%s;", id - target, id - target + 10, id)
	end
	return map
end

function Bartender3.Class.ActionBar.prototype:AddButtonStates(state, page)
	for _,v in pairs(self.buttonobjects) do
		local action = (page == 0) and v.id or (v.rid + ((page - 1) * 12))
		v:SetStateAction(state, action)
	end
	self:AddRightClickState(state)
	self:AddToStateButton(state)
end

function Bartender3.Class.ActionBar.prototype:AddToStateButton(state)
	if not self.statebutton then self.statebutton = {} end
	state = tonumber(state)
	if not tfind(self.statebutton, state) then 
		table.insert(self.statebutton, state)
	end
end

function Bartender3.Class.ActionBar.prototype:ApplyStateButton()
	local states = {}
	for _,v in pairs(self.statebutton) do
		for i=1,2 do
			states[i] = (states[i] or "") .. v .. ":S" .. v .. i .. ";"
		end
	end
	self.frame:SetAttribute("statebutton", states[1])
	self.frame:SetAttribute("statebutton2", states[2])
	--self.statebutton = nil
end
