/*******************************
 *
 *	Fin Core Class
 *
 *  Version: 1.0
 *
 *	Authors: 
 *	The Roundhouse
 *  Paul Lewis
 *
 *  Description:
 *
 *	Handles some of the core functionality we look for from
 *  Fin 2, such as loading dial and AJAX submission or opening
 *  a popup window
 */
 
var FinCore = new Class({
	
	_pageManager:			null,
	_panels:				null,
	_iPad: 					20,
	_tabPanels: 			null,
	_tabs:					null,
	
	// constructor
	initialize: 			function()
	{
		this._panels 		= new Array();
		this._tabPanels 	= new Array();
		this._tabs			= new Array();
		
		// declare to the Universe at large, or at least the browser
		// that we are runnning Fin
		document.FIN 		= true;
	},
	
	// store the local page manager instance
	registerPageManager: 	function(pageManagerInst)
	{
		this._pageManager 	= pageManagerInst;
	},
	
	// getter for the stored local page manager
	getPageManager: 		function()
	{
		return this._pageManager;
	},
	
	// open a pop up window
	openPopup:				function(strURL, strWindowName, iWidth, iHeight, bFixedSize)
	{
		// get a central page position
		var iXPos 			= (Window.getWidth() - iWidth)/2;
		var iYPos 			= (Window.getHeight() - iHeight)/2;
		
		// set some other options
		var strOptions 		= 'width='+iWidth+',height='+iHeight+',screenX='+iXPos+',screenY='+iYPos+',scrollbars=yes'+(bFixedSize?'':',resizable=yes');
		
		// go, go, go!
		var newWindow		= window.open(strURL, strWindowName, strOptions);
		return newWindow;
	},
	
	createPanel: 			function(strName, iWidth, iXPos, iYPos)
	{
		// check for our panel and create if it doesn't exist
		if(!this._panels[strName])
		{
			// create all the divs for this panel
			var divPanel 			= new Element('div');
			divPanel.setProperty('id', strName);
			divPanel.addClass('finfloatingpanel');
			
			// PANEL TOP
			var divPanelTop			= new Element('div');
			var divPanelTopLeft		= new Element('div');
			var divPanelTopMid		= new Element('div');
			var divPanelTopRight	= new Element('div');
			
			// PANEL MID
			var divPanelMid 		= new Element('div');
			var divPanelMidLeft 	= new Element('div');
			var divPanelMidRight 	= new Element('div');
			var divPanelMidLeftRep	= new Element('div');
			var divPanelMidRightRep	= new Element('div');
			
			// PANEL BOTTOM
			var divPanelBottom		= new Element('div');
			var divPanelBottomLeft	= new Element('div');
			var divPanelBottomMid	= new Element('div');
			var divPanelBottomRight	= new Element('div');
			
			// PANEL BUTTONS
			var divPanelButtonMove	= new Element('div');
			var divPanelButtonClose	= new Element('div');
			
			// PANEL CONTENT
			var divPanelContent 	= new Element('div');
			var divPanelContentSpce	= new Element('div');
			
			divPanelContentSpce.setStyle('height', '25px');
			divPanelContent.adopt(divPanelContentSpce);
			
			divPanel._divContent	= divPanelContent;
			divPanel._divFooter		= divPanelBottom;
			divPanel._divCloseBtn	= divPanelButtonClose;
			divPanel.getContentArea	= function(){ return this._divContent; }
			divPanel.getFooterArea	= function(){ return this._divFooter; }
			divPanel.getCloseButton = function(){ return this._divCloseBtn; }
			
			// position all the divs inside the
			// correct parent divs
			divPanel.adopt(divPanelTop);
			divPanelTop.adopt(divPanelTopLeft);
			divPanelTop.adopt(divPanelTopRight);
			divPanelTop.adopt(divPanelTopMid);
			
			divPanel.adopt(divPanelMidLeft);
			divPanelMidLeft.adopt(divPanelMidRight);
			divPanelMidRight.adopt(divPanelMidLeftRep);
			divPanelMidRight.adopt(divPanelMidRightRep);
			divPanelMidRight.adopt(divPanelContent);
			
			divPanel.adopt(divPanelBottom);
			divPanelBottom.adopt(divPanelBottomLeft);
			divPanelBottom.adopt(divPanelBottomRight);
			divPanelBottom.adopt(divPanelBottomMid);
			
			// sort out the buttons
			divPanel.adopt(divPanelButtonClose);
			divPanel.adopt(divPanelButtonMove);
			divPanelButtonClose.setStyle('right', '17px');
			divPanelButtonMove.setStyle('right', '42px');
			
			// set the width, height and apply the class
			divPanel.setStyle('width', iWidth+'px');
			divPanel.setStyle('z-depth', '12299');
			divPanel.addClass('fincontentpanel');
			
			// set the style of each top div
			divPanelTop.addClass('fincontentpaneltop');
			divPanelTopLeft.addClass('fincontentpaneltopleft');
			divPanelTopMid.addClass('fincontentpaneltopmid');
			divPanelTopRight.addClass('fincontentpaneltopright');
			
			// set the style of each middle div
			divPanelMidLeft.addClass('fincontentpanelmidleft');
			divPanelMidRight.addClass('fincontentpanelmidright');
			
			divPanelMidLeftRep.addClass('fincontentpanelmidleftrepeat');
			divPanelMidRightRep.addClass('fincontentpanelmidrightrepeat');
			
			// set the style of each bottom div
			divPanelBottom.addClass('fincontentpanelbottom');
			divPanelBottomLeft.addClass('fincontentpanelbottomleft');
			divPanelBottomMid.addClass('fincontentpanelbottommid');
			divPanelBottomRight.addClass('fincontentpanelbottomright');
			
			// configure the buttons
			divPanelButtonMove.addClass('fincontentpanelbutton');
			divPanelButtonMove.addClass('fincontentpanelbuttonmove');
			divPanelButtonClose.setProperty('daddy', strName);
			
			divPanelButtonClose.addClass('fincontentpanelbutton');
			divPanelButtonClose.addClass('fincontentpanelbuttonclose');
			
			divPanelContent.addClass('fincontentpanelcontent');
											
			divPanelButtonMove.addEvent('mouseover', function(){ this.setStyle('cursor', 'pointer'); this.setStyle('cursor', 'hand'); });
			divPanelButtonClose.addEvent('mouseover', function(){ this.setStyle('cursor', 'pointer'); this.setStyle('cursor', 'hand'); });
			divPanelButtonClose.addEvent('click', function(){ finCore.hidePanel(this.getProperty('daddy')); });
					
			// if we have positional info, apply it
			divPanel.setStyle('left', (iXPos||((Window.getWidth()-iWidth)/2))+'px');
			divPanel.setStyle('top', (iYPos||((Window.getHeight()-300)/2))+'px');
			
			// add the panel to the body tag
			$(document.body).adopt(divPanel);
			
			// set up dragging, surprisingly named makeDraggable...
			if($(strName))
				$(strName).makeDraggable({handle:divPanelButtonMove, container:$(document.body)});
			
			
			// by default hide it
			divPanel.setOpacity(0);
			
			// store it for future use
			this._panels[strName] 	= divPanel;
			
			$(strName)._objManager	= divPanel;
			$(strName).getManager	= function()
			{
				return this._objManager;
			}
		}
		
		return this._panels[strName];
	},
	
	createTabPanel:		function(strName, opts)
	{
		if(!this._tabPanels[strName])
		{
			// create a holder div
			var divTabInterface 				= new Element('div');
			var divTabHolder 					= new Element('div');
			var divTabClickBlocker				= new Element('div');
			var aTabClickBlocker				= new Element('a');
			var divTabClickBlockerDial			= new Element('div');
			var divTabClickBlockerDialBG		= new Element('div');
			var divContentHolderWrapper			= new Element('div');
			var divContentHolder 				= new Element('div');
			var divContentHolderInner 			= new Element('div');
			var divTabPanelLocker				= new Element('div');
			var aTabPanelLocker					= new Element('a');
			
			// give the tab panel its id and give it a blank array
			// for the tabs it holds
			divTabInterface.setProperty('id', strName);
			divTabInterface._tabs 				= new Array();
			divTabInterface._activeTab 			= null;
			divTabInterface._divTabClickBlocker	= divTabClickBlocker;
			divTabInterface._divTabPanelLocker 	= divTabPanelLocker;
			divTabInterface.storeTab 			= function(divNewTab)
												  {
													  // store the tab
													  this._tabs.push(divNewTab);
													  
													  // tell the tab who owns it
													  divNewTab.daddy = this;
													  
													  // and set it to be the 'active' tab
													  // if it is the first tab added
													  if(this._tabs.length == 1) 
													  	this.setActiveTab(divNewTab);
													
													  // return the 'is first' variable
													  return (this._tabs.length==1);
												  };
												  
			divTabInterface.blockClicks			= function(bActive)
												  {
													  if(bActive)
													  	this._divTabClickBlocker.removeClass('hidden');
													  else
													  	this._divTabClickBlocker.addClass('hidden');
												  }
			
			divTabInterface.lockPanel			= function(bActive)
												  {
													  if(bActive)
													  	this._divTabPanelLocker.removeClass('hidden');
													  else
													  	this._divTabPanelLocker.addClass('hidden');
												  }
			
												  
			divTabInterface.setActiveTab 		= function(divActiveTab) { this._activeTab = divActiveTab; };
			divTabInterface.getActiveTab 		= function() { return this._activeTab; };
			
			// *** dunno if this is the right place for this ... or whether i'm actually going about
			// this the right way at all ... but i need to get a reference to a specific tab somehow!
			divTabInterface.getSpecificTab 		= function(strTabToFind)
												  {
													  var tabToReturn = null;
													  
													  for(var iLoop = 0; iLoop < this._tabs.length; iLoop++)
													  {
														  if(this._tabs[iLoop].tablabel == strTabToFind)
														  {
															tabToReturn = this._tabs[iLoop];
															break;
														  }
													  }
													  
													  return tabToReturn;
												  };
			
			aTabClickBlocker.setProperty('href', 'javascript:alert("This tab is currently processing. Please wait.")');
			aTabPanelLocker.setProperty('href', 'javascript:alert("This tab is currently locked. Please save or close the current item.")');			
			
			// have the interface adopt the tab holder
			divTabInterface.adopt(divTabHolder);
			divTabInterface.adopt(divContentHolderWrapper);
			divTabInterface.adopt(divTabClickBlocker);
			divTabInterface.adopt(divTabPanelLocker);
			
			divContentHolderWrapper.adopt(divContentHolder);
			divContentHolder.adopt(divContentHolderInner);
			
			divTabInterface._divTabHolder 				= divTabHolder;
			divTabInterface._divContentHolder 			= divContentHolderInner;
			divTabInterface._divContentHolderWrapper	= divContentHolderWrapper;
			divTabInterface.getTabHolder				= function() { return this._divTabHolder; };
			divTabInterface.getContentHolder			= function() { return this._divContentHolder; };
			divTabInterface.getContentHolderWrapper		= function() { return this._divContentHolderWrapper; };
			
			// set the classes for the interface content
			divTabHolder.addClass('fintabholder');
			divContentHolderWrapper.addClass('fintabcontentholderwrapper');
			divContentHolder.addClass('fintabcontentholder');
			divContentHolderInner.addClass('fintabcontentholderinner');
			divTabClickBlocker.addClass('fintabholderclickblocker');
			divTabClickBlockerDialBG.addClass('fintabholderclickblockerdialbg');
			divTabClickBlockerDial.addClass('fintabholderclickblockerdial');
			divTabClickBlocker.adopt(aTabClickBlocker);
			divTabClickBlocker.adopt(divTabClickBlockerDialBG);
			divTabClickBlocker.adopt(divTabClickBlockerDial);
			aTabClickBlocker.setOpacity(0.8);
			divTabClickBlocker.addClass('hidden');
			
			divTabPanelLocker.addClass('fintabholderpanellocker');
			divTabPanelLocker.adopt(aTabPanelLocker);
			aTabPanelLocker.setOpacity(0.8);
			divTabPanelLocker.addClass('hidden');
			
			// enforce that we have some options
			opts								= opts || {};
			
			// decide whether its a left, right or full width panel
			switch(opts.strPosition)
			{
				case 'Left':	divTabInterface.addClass('finlefttab');
								break;
				case 'Right':	divTabInterface.addClass('finrighttab');
								break;
				default:		divTabInterface.addClass('finfullwidthtab');
								break;
			}
			
			// adopt the interface and a clearing div
			$('fincontainer').adopt(divTabInterface);
						
			this._tabPanels[strName] = divTabInterface;
		}
		return this._tabPanels[strName];
	},
	
	createDatePicker:	function(strName)
	{
		var dateContainer		= this.createPanel(strName, 260);
		var datePicker 			= new DatePicker();
		datePicker.setContainer(dateContainer);		
		datePicker.writeCalendar();
		return datePicker;
	},
	
	createTab:			function(strName, opts)
	{
		if(!this._tabPanels[strName])
			alert(strName + ' tab panel does not exist');
		else
		{
			// grab the div
			var divTabInterface 		= this._tabPanels[strName];
			
			// insert a tab in
			var divTabHolder 			= divTabInterface.getTabHolder();
			var divNewTab 				= new Element('div');
			var divNewTabLabel			= new Element('h3');
			var divNewContent			= new Element('div');
			
			//clearing div
			var divClear				= new Element('div');
			divClear.addClass("clear");
			
			// enforce good options
			opts						= opts || {};
			
			// set our label
			divNewTabLabel.setHTML(opts.strLabel || 'No Label');
			divNewTab.tablabel 			= divNewTabLabel.innerHTML;
			
			divNewTab._divNewTabLabel	= divNewTabLabel;
			divNewTab.getTabLabel		= function()
			{
				return this._divNewTabLabel;
			}
			
			divNewTab.setTabLabel		= function(strLabel)
			{
				this.tablabel = strLabel;
				this._divNewTabLabel.setHTML(strLabel);
			}
			
			// put the label inside the tab and put the tab inside the holder
			divNewTab.adopt(divNewTabLabel);
			divTabHolder.adopt(divNewTab);
			
			// set some classes
			divNewTab.addClass('fintab');
			divNewContent.addClass('fintabcontent');
			
			// now create a content area and assign it to the tab
			divNewTab._divContent 		= divNewContent;
			divNewTab.getContentDiv		= function() { return this._divContent; };
			
			// throw the new content into the content holder
			var divContentHolder 		= divTabInterface.getContentHolder();
			divContentHolder.adopt(divNewContent);
			
			divNewContent.setHTML(opts.strContent || '');
			divNewContent._divParentTab	= divNewTab;
			divNewContent.getParentTab	= function() { return this._divParentTab; };
			
			// store the tab in the tab interface's array of tabs
			var firstTab 				= divTabInterface.storeTab(divNewTab);
			
			// if this isn't the first tab stored, fade it out
			if(!firstTab)
			{
				divNewTab.setOpacity(0.5);
				divNewContent.addClass('hidden');
				this.addTabBehaviour(divNewTab);
			}
			else
				this.removeTabBehaviour(divNewTab);
			
			this._tabs.push(divNewTab);
			
			return divNewTab;
		}
	},
	
	editTabLabel:		function(strOldLabel, strNewLabel)
	{
		for(var i = 0; i < this._tabs.length; i++)
		{
			if (this._tabs[i].getTabLabel().innerHTML == strOldLabel)
			{
				this._tabs[i].setTabLabel(strNewLabel);
				break;
			}
		}
	},
	
	addTabBehaviour: 	function(divTab)
	{
		// add event listeners
		divTab.onmouseover 	= function(){ this.setStyle('cursor', 'pointer'); this.setStyle('cursor', 'hand'); };
		divTab.onclick		= function(){	
											finCore.showContent(this); 
											// if we've got a tabpanel called 'tabfunctions' i.e. we're in news or 
											// mailing list add a new event which fires when we change between tabs
											if($('tabfunctions'))
											{
												this.fireEvent('tabchanged', this);
											}
										};
	},
	
	removeTabBehaviour: function(divTab)
	{
		// remove event listeners
		divTab.onmouseover 	= function(){ this.setStyle('cursor', 'default');};
		divTab.onmouseover();
		divTab.onclick		= null;
	},
	
	showContent: 		function(divTab, bKeepHidden)
	{
		
		// locate the tab panel this tab belongs to
		var divTabPanel 			= divTab.daddy;
		
		// now located, lets see if we have anything
		// to do before switching
		if(divTab.preContentSwitch)
			divTab.preContentSwitch();
		
		// fade off the existing tab
		divTabPanel.getActiveTab().setOpacity(0.5);
		divTabPanel.getActiveTab().getContentDiv().addClass('hidden');
		
		this.addTabBehaviour(divTabPanel.getActiveTab());
				
		// set this new tab as our active one
		divTabPanel.setActiveTab(divTab);
		
		// remove tab behaviours from our new tab
		this.removeTabBehaviour(divTab);
		
		// unhide our new content
		divTab.getContentDiv().removeClass('hidden');
		divTab.getContentDiv().setOpacity(0);
		
		if(!bKeepHidden)
		{
			// fade it in for showbiz
			new Fx.Style(divTab, 'opacity', {duration:700, transition:Fx.Transitions.expoInOut}).start(0.5,1);
			new Fx.Style(divTab.getContentDiv(), 'opacity', {duration:700, transition:Fx.Transitions.expoInOut}).start(0,1);
		}
		else
		{
			// since we use the keep hidden boolean to 
			// not fade the content in, we should
			// just set the tab up to full opacity
			divTab.setOpacity(1);
		}
		
		if(placeFooter)
			placeFooter();
			
		// and do anything required post switch
		// (such as activating DnD)
		if(divTab.postContentSwitch)
			divTab.postContentSwitch();
		
	},
	
	showPanel: 			function(strName)
	{
		if(!this._panels[strName])
			alert(strName + ' panel does not exist');
		else
		{
			if($(strName).onPreShow)
				$(strName).onPreShow();
			
			// turn it on or off
			if($(strName).getStyle('opacity') < 1)
				new Fx.Style(strName, 'opacity', {duration:700, transition:Fx.Transitions.expoInOut, onComplete:$(strName).onShow || function(){}}).start(0,1);
		
			$(strName).setStyle('display','');
			
			// return a reference
			return this._panels[strName];	
		}
	},
	
	hidePanel: 			function(strName)
	{
		if(!this._panels[strName])
			alert(strName + ' panel does not exist');
		else
		{
			if($(strName).onPreHide)
				$(strName).onPreHide();
			
			// turn it on or off
			if($(strName).getStyle('opacity') > 0)
				new Fx.Style(strName, 'opacity', {duration:700, transition:Fx.Transitions.expoInOut, onComplete:$(strName).onHide || function(){}}).start(1,0);
		
			$(strName).setStyle('display','none');
		
			// return a reference
			return this._panels[strName];	
		}		
	},
	
	// generic function to return a nicely formatted string
	// representation of a number of bytes
	formatFileSize: 		function(iBytes)
	{
		var strFormatted	= iBytes + ' bytes';;
		var iKilobytes		= iBytes / 1024;
		var iMegabytes		= iKilobytes / 1024;
		
		if(iKilobytes > 0.5)
			strFormatted 	= Math.round(iKilobytes*10)/10 + 'Kb';
		
		if(iMegabytes > 0.5)
			strFormatted 	= Math.round(iMegabytes*10)/10 + 'Mb';
		
		return strFormatted;
	},
	
	//Generates a div containing three link elements commonly used
	//by edit panels in fin and returns the div and anchors in an array
	//
	//strItem = name of module or object being edited - used to generate element IDs
	getEditButtons:		function(strItem)
	{
		var div			= new Element('div');
		var aBack		= new Element('a');
		var aSave		= new Element('a');
		var aDelete		= new Element('a');
		
		div.addClass('divEditButtons');
		aBack.addClass('backButton');
		aBack.setProperty('id','backButton_'+strItem);
		aSave.addClass('saveButton');
		aSave.setProperty('id','saveButton_'+strItem);
		aDelete.addClass('deleteButton');
		aDelete.setProperty('id','deleteButton_'+strItem);
		
		var returnArray	= new Array();
		
		returnArray.push(div);
		returnArray.push(aBack);
		returnArray.push(aSave);		
		returnArray.push(aDelete);
		
		for(var i = 1; i < returnArray.length; i++)
		{
			returnArray[i].setProperty('href','javascript:void(0);');
			div.adopt(returnArray[i]);
		}
		
		return returnArray;
	},	
	
	// here we need to submit a form via AJAX and pass the
	// result to the local page manager.
	submitForm: 			function(strFormId, strRequestURL, fnResponse, divReplaceWithLoad)
	{		
		// pass the form over to the local page manager to 
		// make sure that the form validates
		if(this._pageManager.validate(strFormId))
		{
			var objRequestVars = this._pageManager.getRequestObject(strFormId);
			
			// now create an AJAX request to go off and deal with the form
			if(this._pageManager[fnResponse])
			{
				// send off the form
				var objRequest 		= this._pageManager.getRequestObject(strFormId);
				if(objRequest)
					new Ajax(strRequestURL, {onComplete:this._pageManager[fnResponse], postBody:objRequest}).request();
			
				// if we need to do the load dial, give that a whirl
				if(divReplaceWithLoad)
				{
					$(divReplaceWithLoad).addClass('hidden');
					
					// check to see if our dial already exists
					if(!$('finloaddial'))
					{
						// create the element with styles
						var finLoadDial 		= new Element('div');
						finLoadDial.setProperty('id', 'finloaddial');
						finLoadDial.setStyles({ width: 				'80px',
												height: 			'80px',
												backgroundImage: 	'url(../../z_images/misc/anim_load_dial.gif)',
												backgroundRepeat:	'no-repeat',
												backgroundPosition: 'center',
												margin:				'0 auto'
											  });
						finLoadDial.injectAfter(divReplaceWithLoad);
					}
				}
			}
			else
				alert('Unable to find the function: ' + fnResponse);
		}
		
		return false;
	}
});
 
var finCore	= new FinCore();
