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

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
if not nUI_ChatFrameOptions then nUI_ChatFrameOptions = {}; end

local CreateFrame = CreateFrame;
local MouseIsOver = MouseIsOver;

FCF_SetButtonSide    = function() end;
FCF_UpdateButtonSide = function() end;		

-------------------------------------------------------------------------------
-- default configuration for the chat frames

nUI_DefaultConfig.ChatFrame =
{	
	anchor =
	{
		anchor_pt   = "BOTTOMRIGHT",
		relative_to = "nUI_Dashboard",
		relative_pt = "CENTER",
		xOfs        = -685,
		yOfs        = -174,
	},	
	
	options = 
	{
		strata   = "BACKGROUND",
		level    = 3,
		scale    = 1,
		height   = 290,
		width    = 585,
		fontsize = 11,
		btn_size = 65,
		btn_gap  = -8,

		background =
		{
			backdrop =
			{
				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 },
			},
			
			color =
			{
				border = { r = 1, g = 1, b = 1, a = 1 },
				backdrop = { r = 0, g = 0, b = 0, a = 0.85 },
			},
		},
	},	
};

-------------------------------------------------------------------------------
-- chat frame event management

local frame    = CreateFrame( "Frame", "nUI_ChatFrame", nUI_Dashboard.Anchor );
nUI.chat_frame = frame;

local function onChatFrameEvent()

	if event == "VARIABLES_LOADED" then

		nUI:registerScalableFrame( frame );		
		nUI_ChatFrame:configFrame();
		
	else

		frame.texture = frame:CreateTexture();
		frame.texture:SetAllPoints( nUI.chat_frame );
	
		-- relocate the chat frame to the area we have set aside for it on the dashboard
			
		FCF_SetLocked( DEFAULT_CHAT_FRAME, nil );
		MOVING_CHAT_FRAME = DEFAULT_CHAT_FRAME;
		DEFAULT_CHAT_FRAME:StartMoving();
		DEFAULT_CHAT_FRAME:StartSizing();
		DEFAULT_CHAT_FRAME:SetParent( nUI.chat_frame );
		DEFAULT_CHAT_FRAME:ClearAllPoints();
		DEFAULT_CHAT_FRAME:SetPoint( "BOTTOMRIGHT", nUI.chat_frame, "BOTTOMRIGHT", -5, 6 );
		DEFAULT_CHAT_FRAME:SetPoint( "TOPLEFT", nUI.chat_frame, "TOPLEFT", 4, -5 );
		DEFAULT_CHAT_FRAME:Hide();
		DEFAULT_CHAT_FRAME:StopMovingOrSizing();
		
		MOVING_CHAT_FRAME = nil;
	
		-- set strata, etc, for all defined frames, make sure they're all docked
		
		for i=1, NUM_CHAT_WINDOWS do
			
			if i ~= 2 then -- we handle the combat log separately
				
				local cframe  = _G["ChatFrame"..i];
		
				if i == 1 or cframe.isDocked then
								
					cframe:SetUserPlaced( true );
					
					FCF_SetLocked( cframe, 1 );
					FCF_SetWindowAlpha( cframe, 0 );
					
				end
				
				-- relocate the chat frame buttons
		
				local bottom  = _G["ChatFrame"..i.."BottomButton"];
				local down    = _G["ChatFrame"..i.."DownButton"];
				local up      = _G["ChatFrame"..i.."UpButton"];
				
				bottom:SetAlpha( 0 );			
				down:SetAlpha( 0 );			
				up:SetAlpha( 0 );
					
				-- set method to show or hide the scroll buttons based on whether or
				-- not the mouse is in the frame
				
				cframe.showButtons = function( enabled )
	
					if enabled ~= cframe.buttons_visible then
						
						cframe.buttons_visible = enabled;
						bottom:SetAlpha( enabled and 1 or 0 );
						down:SetAlpha( enabled and 1 or 0 );
						up:SetAlpha( enabled and 1 or 0 );
											
					end
				end
				
				-- allow scrolling of the combat log frame with the mouse wheel
				
				cframe:EnableMouseWheel( true );	
				
				cframe:SetScript( "OnMouseWheel", 
					function()
						if arg1 > 0 then cframe:ScrollUp();
						else cframe:ScrollDown();
						end	
					end	
				);		
				
			end
		end
		
		-- relocate the chat frame edit box in the same manner
		
		local width = (ChatFrameEditBox:GetRight() - ChatFrameEditBox:GetLeft()) / ChatFrameEditBox:GetEffectiveScale();
		
		ChatFrameEditBox:SetParent( nUI.chat_frame );
		ChatFrameEditBox:SetScale( 0.8 );
		ChatFrameEditBox:ClearAllPoints();
		ChatFrameEditBox:SetPoint( "TOPLEFT", nUI.chat_frame, "TOPLEFT", 0, 1 );
		ChatFrameEditBox:SetPoint( "TOPRIGHT", nUI.chat_frame, "TOPRIGHT", 0, 1 );
		ChatFrameEditBox:SetFrameStrata( DEFAULT_CHAT_FRAME:GetFrameStrata() );
		ChatFrameEditBox:SetFrameLevel( DEFAULT_CHAT_FRAME:GetFrameLevel()+2 );
		
		ChatFrameMenuButton:ClearAllPoints();
		ChatFrameMenuButton:SetPoint( "BOTTOM", ChatFrame1UpButton, "TOP", 0, -6 );
		ChatFrameMenuButton:Hide(); -- be gone pest
		
	end
end

frame:SetScript( "OnEvent", onChatFrameEvent );
frame:RegisterEvent( "VARIABLES_LOADED" );
frame:RegisterEvent( "PLAYER_LOGIN" );

-------------------------------------------------------------------------------

local mouseover_timer = 0;

local function onChatFrameUpdate( who, elapsed )

	mouseover_timer = mouseover_timer + elapsed;
	
	if mouseover_timer > 0.2 then -- 5 fps is plenty fast enough to show these buttons
	
		mouseover_timer = 0;
	
		for i=1, NUM_CHAT_WINDOWS do

			if i ~= 2 then -- skip combat log
					
				local cframe = _G["ChatFrame"..i];
				
				if cframe.showButtons then
					cframe.showButtons( MouseIsOver( cframe ) );
				end
			end
		end
	end
end

frame:SetScript( "OnUpdate", onChatFrameUpdate );

-------------------------------------------------------------------------------
-- adjust the size of the chat frame according the screen scale

frame.applyScale = function( scale )
	
	local options  = frame.options;
	local anchor   = scale and frame.anchor or nil;
	local scale    = scale or frame.scale or 1;
	local width    = options.width  * scale * nUI.scale;
	local height   = options.height * scale * nUI.scale;
	local fontsize = options.fontsize * scale * nUI.scale;
	local btn_size = options.btn_size * scale * nUI.scale;
	
	frame.scale = scale;
	
	if frame.width  ~= width 
	or frame.height ~= height
	then
		
		frame.width = width;
		frame.height = height;
		
		frame:SetWidth( width );
		frame:SetHeight( height );
		
		for i=1, NUM_CHAT_WINDOWS do
			
			local cframe  = _G["ChatFrame"..i];
	
			if i ~= 2 and (i == 1 or cframe.isDocked) then
							
				cframe:SetUserPlaced( true );
				
				FCF_SetLocked( cframe, 1 );
				FCF_SetWindowAlpha( cframe, 0 );

				-- size the frame
				
				if i == 1 then
					cframe:SetWidth( cframe:GetRight() - cframe:GetLeft() );
					cframe:SetHeight( cframe:GetTop() - cframe:GetBottom() );
				else
					cframe:SetWidth( ChatFrame1:GetWidth() );
					cframe:SetHeight( ChatFrame1:GetHeight() );
				end								
			end
		end
	end
	
	-- set the size of the scroll buttons in the chat frames
	
	if frame.btn_size ~= btn_size then
		frame.btn_size = btn_size;

		for i=1, NUM_CHAT_WINDOWS do

			if i ~= 2 then
					
				-- size the scroll buttons
	
				local size    = 45 * nUI.scale;
				local bottom  = _G["ChatFrame"..i.."BottomButton"];
				local down    = _G["ChatFrame"..i.."DownButton"];
				local up      = _G["ChatFrame"..i.."UpButton"];
				
				bottom:SetWidth( size );
				bottom:SetHeight( size );
				
				down:SetWidth( size );
				down:SetHeight( size );
				
				up:SetWidth( size );
				up:SetHeight( size );

			end
		end
	end
	
	-- set the chat frame font size
	
	if frame.fontsize ~= fontsize then
		frame.fontsize = fontsize;
		
		for i=1, NUM_CHAT_WINDOWS do
			if i ~= 2 then
				_G["ChatFrame"..i]:SetFont( nUI_L["font1"], fontsize * 2, "OUTLINE" );
			end
		end
	end
	
	-- set the locations of the buttons relative to their chat frame
	
	for i=1, NUM_CHAT_WINDOWS do
			
		if i ~= 2 then
				
			local bottom  = _G["ChatFrame"..i.."BottomButton"];
			local down    = _G["ChatFrame"..i.."DownButton"];
			local up      = _G["ChatFrame"..i.."UpButton"];
			
			bottom:ClearAllPoints();
			bottom:SetPoint( "BOTTOMRIGHT", _G["ChatFrame"..i], "BOTTOMRIGHT", 2, -8 * nUI.scale );
			
			down:ClearAllPoints();
			down:SetPoint( "BOTTOM", bottom, "TOP", 0, options.btn_gap * nUI.scale );
			
			up:ClearAllPoints();				
			up:SetPoint( "BOTTOM", down, "TOP", 0, options.btn_gap * nUI.scale );
			
		end		
	end	
	
	if anchor then frame.applyAnchor( anchor ); end
	
end

-------------------------------------------------------------------------------
-- anchor the chat frame

frame.applyAnchor = function( anchor )

	local anchor     = anchor or frame.anchor or {};
	local xOfs       = anchor.xOfs * nUI.scale;
	local yOfs       = anchor.yOfs * nUI.scale;	
	frame.anchor     = anchor;
	
	if frame.anchor_pt   ~= anchor.anchor_pt
	or frame.relative_to ~= anchor.relative_to
	or frame.relative_pt ~= anchor.relative_pt
	or frame.xOfs        ~= xOfs
	or frame.yOfs        ~= yOfs
	then
		
		frame.anchor_pt = anchor.anchor_pt;
		frame.relative_to = anchor.relative_to;
		frame.relative_pt = anchor.relative_pt;
		frame.xOfs        = xOfs;
		frame.yOfs        = yOfs;
		
		frame:ClearAllPoints();
		frame:SetPoint( anchor.anchor_pt, anchor.relative_to, anchor.relative_pt, xOfs, yOfs );
		
	end
end

-------------------------------------------------------------------------------
-- apply a set of configuration options to the chat frame

frame.applyOptions = function( options )

	frame.options = options;
	
	frame:SetFrameStrata( options.strata or nUI_Dashboard.Anchor:GetFrameStrata() );
	frame:SetFrameLevel( options.level or nUI_Dashboard.Anchor:GetFrameLevel()+2 );

	for i=1, NUM_CHAT_WINDOWS do

		if i ~= 2 then
			
			local cframe = _G["ChatFrame"..i];
			
			cframe:SetFrameStrata( frame:GetFrameStrata() );
			cframe:SetFrameLevel( frame:GetFrameLevel()+1 );
			
		end		
	end
		
	if options.background then
		
		local backdrop_color = options.background.color.backdrop;
		local border_color   = options.background.color.border;
		
		frame:SetBackdrop( options.background.backdrop );
		frame:SetBackdropColor( backdrop_color.r, backdrop_color.g, backdrop_color.b, backdrop_color.a );
		frame:SetBackdropBorderColor( border_color.r, border_color.g, border_color.b, border_color.a );
		
	else
		
		frame:SetBackdrop( nil );
		
	end
	
	frame.applyScale( frame.scale or 1 );
	
end

-------------------------------------------------------------------------------

function nUI_ChatFrame:configFrame( use_default )
	
	local default = nUI_DefaultConfig.ChatFrame;
	local config  = nUI_ChatFrameOptions or {};
	
	if not config.anchor then config.anchor = {}; end
	if not config.options then config.options = {}; end
	if not config.options.background then config.options.background = {}; end
	if not config.options.background.backdrop then config.options.background.backdrop = {}; end
	if not config.options.background.backdrop.insets then config.options.background.backdrop.insets = {}; end
	if not config.options.background.color then config.options.background.color = {}; end
	if not config.options.background.color.border then config.options.background.color.border = {}; end
	if not config.options.background.color.backdrop then config.options.background.color.backdrop = {}; end
	
	if use_default then
		
		config.anchor.anchor_pt   = default.anchor.anchor_pt;
		config.anchor.relative_to = default.anchor.relative_to;
		config.anchor.relative_pt = default.anchor.relative_pt;
		config.anchor.xOfs        = default.anchor.xOfs;
		config.anchor.yOfs        = default.anchor.yOfs;
		
		config.options.strata   = default.options.strata;
		config.options.level    = default.options.level;
		config.options.scale    = default.options.scale;
		config.options.height   = default.options.height;
		config.options.width    = default.options.width;
		config.options.fontsize = default.options.fontsize;
		config.options.btn_size = default.options.btn_size;
		config.options.btn_gap  = default.options.btn_gap;
		
		config.options.background.backdrop.bgFile   = default.options.background.backdrop.bgFile;
		config.options.background.backdrop.edgeFile = default.options.background.backdrop.edgeFile;
		config.options.background.backdrop.tile     = default.options.background.backdrop.tile;
		config.options.background.backdrop.tileSize = default.options.background.backdrop.tileSize;
		config.options.background.backdrop.edgeSize = default.options.background.backdrop.edgeSize;
		
		config.options.background.backdrop.insets.left   = default.options.background.backdrop.insets.left;
		config.options.background.backdrop.insets.right  = default.options.background.backdrop.insets.right;
		config.options.background.backdrop.insets.top    = default.options.background.backdrop.insets.top;
		config.options.background.backdrop.insets.bottom = default.options.background.backdrop.insets.bottom;
		
		config.options.background.color.border.r = default.options.background.color.border.r;
		config.options.background.color.border.g = default.options.background.color.border.g;
		config.options.background.color.border.b = default.options.background.color.border.b;
		config.options.background.color.border.a = default.options.background.color.border.a;
		
		config.options.background.color.backdrop.r = default.options.background.color.backdrop.r;
		config.options.background.color.backdrop.g = default.options.background.color.backdrop.g;
		config.options.background.color.backdrop.b = default.options.background.color.backdrop.b;
		config.options.background.color.backdrop.a = default.options.background.color.backdrop.a;
		
	else
		
		config.anchor.anchor_pt   = strupper( default.anchor.anchor_pt or config.anchor.anchor_pt );
		config.anchor.relative_to = default.anchor.relative_to or config.anchor.relative_to;
		config.anchor.relative_pt = strupper( default.anchor.relative_pt or config.anchor.relative_pt );
		config.anchor.xOfs        = tonumber( default.anchor.xOfs or config.anchor.xOfs );
		config.anchor.yOfs        = tonumber( default.anchor.yOfs or config.anchor.yOfs );
		
		config.options.strata   = strupper( default.options.strata or config.options.strata );
		config.options.level    = tonumber( default.options.level or config.options.level );
		config.options.scale    = tonumber( default.options.scale or config.options.scale );
		config.options.height   = tonumber( default.options.height or config.options.height );
		config.options.width    = tonumber( default.options.width or config.options.width );
		config.options.fontsize = tonumber( default.options.fontsize or config.options.fontsize );
		config.options.btn_size = tonumber( default.options.btn_size or config.options.btn_size );
		config.options.btn_gap  = tonumber( default.options.btn_gap or config.options.btn_gap );
		
		config.options.background.backdrop.bgFile   = default.options.background.backdrop.bgFile or config.options.background.backdrop.bgFile;
		config.options.background.backdrop.edgeFile = default.options.background.backdrop.edgeFile or config.options.background.backdrop.edgeFile;
		config.options.background.backdrop.tile     = default.options.background.backdrop.tile or config.options.background.backdrop.tile;
		config.options.background.backdrop.tileSize = tonumber( default.options.background.backdrop.tileSize or config.options.background.backdrop.tileSize );
		config.options.background.backdrop.edgeSize = tonumber( default.options.background.backdrop.edgeSize or config.options.background.backdrop.edgeSize );
		
		config.options.background.backdrop.insets.left   = tonumber( default.options.background.backdrop.insets.left or config.options.background.backdrop.insets.left );
		config.options.background.backdrop.insets.right  = tonumber( default.options.background.backdrop.insets.right or config.options.background.backdrop.insets.right );
		config.options.background.backdrop.insets.top    = tonumber( default.options.background.backdrop.insets.top or config.options.background.backdrop.insets.top );
		config.options.background.backdrop.insets.bottom = tonumber( default.options.background.backdrop.insets.bottom or config.options.background.backdrop.insets.bottom );
		
		config.options.background.color.border.r = tonumber( default.options.background.color.border.r or config.options.background.color.border.r );
		config.options.background.color.border.g = tonumber( default.options.background.color.border.g or config.options.background.color.border.g );
		config.options.background.color.border.b = tonumber( default.options.background.color.border.b or config.options.background.color.border.b );
		config.options.background.color.border.a = tonumber( default.options.background.color.border.a or config.options.background.color.border.a );
		
		config.options.background.color.backdrop.r = tonumber( default.options.background.color.backdrop.r or config.options.background.color.backdrop.r );
		config.options.background.color.backdrop.g = tonumber( default.options.background.color.backdrop.g or config.options.background.color.backdrop.g );
		config.options.background.color.backdrop.b = tonumber( default.options.background.color.backdrop.b or config.options.background.color.backdrop.b );
		config.options.background.color.backdrop.a = tonumber( default.options.background.color.backdrop.a or config.options.background.color.backdrop.a );
		
	end		

	nUI_ChatFrameOptions = config;
	
	frame.applyOptions( config.options );
	frame.applyAnchor( config.anchor );
	
end
