--[[---------------------------------------------------------------------------

Copyright (c) 2008 by K. Scott Piel 
All Rights Reserved

E-mail: < kscottpiel@gmail.com >
Web:    < http://www.scottpiel.com >

This file is part of nUI.

    nUI is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    nUI is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with nUI.  If not, see <http://www.gnu.org/licenses/>.
	
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

--]]---------------------------------------------------------------------------

if not nUI then nUI = {}; end
if not nUI_DefaultConfig then nUI_DefaultConfig = {}; end

local CreateFrame         = CreateFrame;
local GetBindingKey       = GetBindingKey;
local RegisterStateDriver = RegisterStateDriver;

-------------------------------------------------------------------------------
-- default button bar configurations

nUI_DefaultConfig.ButtonBars =
{
	["nUI_ActionBar"] =
	{
		btn_size = 54,
		gap      = 2,
		anchor   = "BOTTOM",
		xOfs     = 0,
		yOfs     = 123,
		rows     = 1,
		cols     = 12,
		page     = 1,
		binding  = "ACTIONBUTTON",
		label    = nUI_L["pg1 / Action Bar]"],
	},

	-- the Bliz "bottom left" bar

	["nUI_MultiBarBottomLeft"] =
	{		
		btn_size = 54,
		gap      = 2,
		anchor   = "TOPLEFT",
		yOfs     = 117,
		xOfs     = -680,
		rows     = 1,
		cols     = 12,
		page     = 6,
		binding  = "MULTIACTIONBAR1BUTTON",
		label    = nUI_L["pg6 / BottomLeft"],
	},
	
	-- the Bliz "bottom right" bar

	["nUI_MultiBarBottomRight"] =
	{		
		btn_size = 54,
		gap      = 2,
		anchor   = "TOPRIGHT",
		yOfs     = 117,
		xOfs     = 680,
		rows     = 1,
		cols     = 12,
		page     = 5,
		binding  = "MULTIACTIONBAR2BUTTON",
		label    = nUI_L["pg5 / BottomRight"],
	},
	
	-- the Bliz "right 1" bar (aka "left" bar in the Bliz code)

	["nUI_MultiBarLeft"] =
	{		
		btn_size = 48,
		gap      = 2,
		anchor   = "BOTTOMLEFT",
		yOfs     = -250,
		xOfs     = -680,
		rows     = 6,
		cols     = 2,
		page     = 3,
		binding  = "MULTIACTIONBAR3BUTTON",
		label    = nUI_L["pg3 / Right 2"],
	},
		
	-- the Bliz "right 2" bar (aka "right" bar in the Bliz code)
	
	["nUI_MultiBarRight"] =
	{		
		btn_size = 48,
		gap      = 2,
		anchor   = "BOTTOMRIGHT",
		yOfs     = -250,
		xOfs     = 680,
		rows     = 6,
		cols     = 2,
		page     = 4,
		binding  = "MULTIACTIONBAR4BUTTON",
		label    = nUI_L["pg4 / Right"],
	},

	-- bonus bar 1

	["nUI_BonusBar1"] =
	{		
		btn_size = 38,
		gap      = 2,
		anchor   = "BOTTOMLEFT",
		yOfs     = -250,
		xOfs     = -1270,
		rows     = 1,
		cols     = 12,
		page     = 2,
		binding  = "NUIBAR1BUTTON",
		label    = nUI_L["pg2 / nUI Bonus Bar 1"],
	},
		
	-- bonus bar 2
	
	["nUI_BonusBar2"] =
	{		
		btn_size = 38,
		gap      = 2,
		anchor   = "BOTTOMRIGHT",
		yOfs     = -250,
		xOfs     = 1270,
		rows     = 1,
		cols     = 12,
		base_id  = 108,
		binding  = "NUIBAR2BUTTON",
		label    = nUI_L["nUI Bonus Bar 2"],
	},	
};
	
-------------------------------------------------------------------------------
-- button bar event management

nUI_ButtonBars       = CreateFrame( "Frame", "nUI_ButtonBars", WorldFrame );
nUI_ButtonBars.Bars  = {};

function onButtonBarEvent()
		
	if event == "VARIABLES_LOADED" then
		
		nUI:patchConfig();
		nUI:setScale();
		
		-- set up the button bar options
		
		if not nUI_ButtonBarOptions then nUI_ButtonBarOptions = {}; end

		for name in pairs( nUI_DefaultConfig.ButtonBars ) do
				
			nUI_ButtonBars:configBar( name, use_default );
			
		end
		
		-- if we already have bars defined, then put them away before we build a new set
		
		for i in pairs( nUI_ButtonBars.Bars ) do
			
			local bar = nUI_ButtonBars.Bars[i];
			
			bar:UnregisterAllEvents();
			bar:Hide();
			bar:SetParent( nil );
			
			for j in pairs( bar.Buttons ) do
				bar.Buttons[j]:UnregisterAllEvents();
			end
		end
		
		-- create the button bars that are defined
		
		nUI_ButtonBars.Bars = {};
		
		for i in pairs( nUI_ButtonBarOptions ) do
			
			nUI_ButtonBars.Bars[i] = nUI_ButtonBars:createBar( i, nUI_ButtonBarOptions[i] );
					
		end

		-- set up the action bar state driver

		nUI_ActionBar = nUI_ButtonBars.Bars["nUI_ActionBar"];
		
		nUI_ActionBar:SetAttribute( "stateattributes", "2:pg2;3:pg3;4:pg4;5:pg5;6:pg6;7:pg7;8:pg8;9:pg9;10:pg10;11:pg11;*:pg1" );
		nUI_ActionBar:SetAttribute( "attributes-pg1",  "actionpage=1" );
		nUI_ActionBar:SetAttribute( "attributes-pg2",  "actionpage=2" );
		nUI_ActionBar:SetAttribute( "attributes-pg3",  "actionpage=3" );
		nUI_ActionBar:SetAttribute( "attributes-pg4",  "actionpage=4" );
		nUI_ActionBar:SetAttribute( "attributes-pg5",  "actionpage=5" );
		nUI_ActionBar:SetAttribute( "attributes-pg6",  "actionpage=6" );
		nUI_ActionBar:SetAttribute( "attributes-pg7",  "actionpage=7" );
		nUI_ActionBar:SetAttribute( "attributes-pg8",  "actionpage=8" );
		nUI_ActionBar:SetAttribute( "attributes-pg9",  "actionpage=9" );
		nUI_ActionBar:SetAttribute( "attributes-pg10", "actionpage=10" );
		nUI_ActionBar:SetAttribute( "attributes-pg11", "actionpage=11" );
		nUI_ActionBar:SetAttribute( "statemap-page",   "*:$input" );
		
		RegisterStateDriver( nUI_ActionBar, "page", "[bar:2] 2; [bar:3] 3; [bar:4] 4; [bar:5] 5; [bar:6] 6; [bonusbar:1] 7; [bonusbar:2] 8; [bonusbar:3] 9; [bonusbar:4] 10; [bonusbar:5] 11; 1" );	
--		RegisterStateDriver( nUI_ActionBar, "page", "[form:3, stealth] 8; [bar:2] 2; [bar:3] 3; [bar:4] 4; [bar:5] 5; [bar:6] 6; [bonusbar:1] 7; [bonusbar:2] 8; [bonusbar:3] 9; [bonusbar:4] 10; [bonusbar:5] 11; 1" );	

	end
end

nUI_ButtonBars:RegisterEvent( "VARIABLES_LOADED" );
nUI_ButtonBars:SetScript( "OnEvent", onButtonBarEvent );
	
-------------------------------------------------------------------------------
-- set configuration data for a single named bar

function nUI_ButtonBars:configBar( name, use_default )

	local config  = nUI_ButtonBarOptions[name] or {};
	local default = nUI_DefaultConfig.ButtonBars[name] or config;

	if use_default then
		
		config.btn_size = default.btn_size;
		config.gap      = default.gap;
		config.anchor   = default.anchor;
		config.xOfs     = default.xOfs;
		config.yOfs     = default.yOfs;
		config.rows     = default.rows;
		config.cols     = default.cols;
		config.binding  = default.binding;
		config.label    = default.label;
		config.page     = default.page;
		config.base_id  = default.base_id;
				
	else
			
		config.btn_size = tonumber( config.btn_size or default.btn_size );
		config.gap      = tonumber( config.gap or default.gap );
		config.anchor   = strupper( config.anchor or default.anchor );
		config.xOfs     = tonumber( config.xOfs or default.xOfs );
		config.yOfs     = tonumber( config.yOfs or default.yOfs );
		config.rows     = tonumber( config.rows or default.rows );
		config.cols     = tonumber( config.cols or default.cols );
		config.binding  = strupper( config.binding or default.binding );
		config.label    = config.label or default.label;
		config.page     = config.page or default.page;
		config.base_id  = config.base_id or default.base_id;
		
	end
	
	if config.page then config.page = tonumber( config.page ); end
	if config.base_id then config.base_id = tonumber( config.base_id ); end
	
	nUI_ButtonBarOptions[name] = config;
	
end

-------------------------------------------------------------------------------
-- create a new named button bar using the passed layout

function nUI_ButtonBars:createBar( name, layout )
	
	local bar  = CreateFrame( "Frame", name, nUI_Dashboard.Anchor, "SecureStateHeaderTemplate" );
	bar.events = CreateFrame( "Frame", name.."_Events", nUI_ButtonBars );
	bar.layout = layout;
	
	bar:SetBackdrop(
		{
			bgFile   = "Interface\\AddOns\\nUI\\Art\\nUI_BevelboxBg.blp", 
			edgeFile = "Interface\\AddOns\\nUI\\Art\\nUI_BevelboxBorder.blp", 
			tile     = true, 
			tileSize = 1, 
			edgeSize = 12, 
			insets   = {left = 0, right = 0, top = 0, bottom = 0},
		}
	);
	
	bar:SetBackdropColor( 0, 0, 0, 0.35 );

	if layout.page then layout.base_id = (layout.page-1) * 12; end
	
	-- button initialization
	
	bar.Buttons = {};

	for i=1,layout.rows do
	
		bar.Buttons[i] = {};
		
		for j=1,layout.cols do
			
			local id         = (i-1)*layout.cols + j;
			local button     = CreateFrame( "CheckButton", "$parent_Button"..id, bar, "ActionBarButtonTemplate" );
			local key1, key2 = GetBindingKey( layout.binding..i );
			
			bar.Buttons[i][j] = button;
		
			button.action                   = layout.base_id + id;
			button.actionType               = layout.binding;
			button.actionID                 = id;
			button.nUI_CachedClearAllPoints = button.ClearAllPoints;
			button.nUI_CachedSetAllPoints   = button.SetAllPoints;
			button.nUI_CachedSetPoint       = button.SetPoint;
		
			-- for the main action bar, we need the button ID set to support paging
			
			if name == "nUI_ActionBar" then
				button:SetID(id);
				bar:SetAttribute( "addchild", button );
			else
				button:SetAttribute( "action", button.action ); 
			end			
		end
	end

	-- manage the layout of the bar
	
	bar.events:RegisterEvent( "DISPLAY_SIZE_CHANGED" );
	bar.events:RegisterEvent( "PLAYER_LOGIN" );
	bar.events:SetScript( "OnEvent", function() nUI_ButtonBars:layoutFrame( bar ); end );
		
	return bar;
	
end

-------------------------------------------------------------------------------
-- actually perform the layout on the indicated bar. If no layout is passed
-- then the current layout for this bar is used. Otherwise the passed layout
-- will replace the current layout

function nUI_ButtonBars:layoutFrame( bar, layout )

	if layout then bar.layout = layout;
	else layout = bar.layout;
	end
	
	nUI:setScale();
				
	local btn_size    = layout.btn_size * nUI.scale;
	local btn_gap     = layout.gap * nUI.scale;
	
	bar:SetFrameStrata( nUI_Dashboard:GetFrameStrata() );
	bar:SetFrameLevel( nUI_Dashboard:GetFrameLevel()+2 );
	
	for row in pairs( bar.Buttons ) do
		
		for col in pairs( bar.Buttons[row] ) do
			
			local button = bar.Buttons[row][col];
	
			button:SetFrameStrata( bar:GetFrameStrata() );
			button:SetFrameLevel( bar:GetFrameLevel()+1 );
			button:SetScale( btn_size / button:GetHeight() );
	
			button:nUI_CachedClearAllPoints();
			
			if col == 1 and row == 1 then 
				button:nUI_CachedSetPoint( "TOPLEFT", bar, "TOPLEFT", btn_size * 0.05, -btn_size * 0.05 );
			elseif col == 1 then
				button:nUI_CachedSetPoint( "TOPLEFT", bar.Buttons[row-1][1], "BOTTOMLEFT", 0, -btn_gap );
			else 
				button:nUI_CachedSetPoint( "TOPLEFT", bar.Buttons[row][col-1], "TOPRIGHT", btn_gap, 0 );
			end
			
			nUI:initActionButton( button );
			
		end
	end		
	
	bar:SetHeight( layout.rows * btn_size + (layout.rows-1) * btn_gap + btn_size * 0.1 );
	bar:SetWidth( layout.cols * btn_size + (layout.cols-1) * btn_gap + btn_size * 0.1 );
	bar:SetPoint( layout.anchor, nUI_Dashboard, "CENTER", layout.xOfs * nUI.scale, layout.yOfs * nUI.scale );
	
	-- if this is the action bar, then add the paging buttons to it
	
	if bar:GetName() == "nUI_ActionBar" then

		ActionBarUpButton:SetParent( bar );
		ActionBarUpButton:SetFrameStrata( bar:GetFrameStrata() );
		ActionBarUpButton:SetFrameLevel( bar:GetFrameLevel() );
		ActionBarUpButton:SetScale( 1.5 * nUI.scale );
		ActionBarUpButton:ClearAllPoints();
		ActionBarUpButton:SetPoint( "TOPLEFT", bar, "TOPRIGHT", -10 * nUI.scale, 15 * nUI.scale );
		ActionBarUpButton:Show();
	
		ActionBarDownButton:SetParent( bar );
		ActionBarDownButton:SetFrameStrata( bar:GetFrameStrata() );
		ActionBarDownButton:SetFrameLevel( bar:GetFrameLevel() );
		ActionBarDownButton:SetScale( 1.5 * nUI.scale );
		ActionBarDownButton:ClearAllPoints();
		ActionBarDownButton:SetPoint( "BOTTOMLEFT", bar, "BOTTOMRIGHT", -10 * nUI.scale, -15 * nUI.scale  );
		ActionBarDownButton:Show();
		
	end
	
end
