/**
 *	SPIRIT 3.91/4 Transitional :: AJAX CONTENT FRAMEWORK
 *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *	BETA BETA BETA BETA BETA BETA BETA BETA BETA BETA 
 *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *	Copyright : Isotope Communications Ltd 2006
 *	Author	  : Jim Morrison
 *	Version	  : 0.1 ( alpha )
 *	Purpose	  : Experimental implementation of AJAX
 */
 
var SpiritAjaxFramework = new Class.create();

SpiritAjaxFramework.prototype = {
	
	initialize: function ( options ){
		this.base_uri = document.location.pathname + document.location.search + document.location.hash;
		this.default_block = (typeof(DEFAULT_ajax_block)!='undefined') ? DEFAULT_ajax_block : 'SAF_BODY';
		this.options = $H(options)
	},
	
	post: function(u,t,i,q,n,p){
		return this.navigate(u,t,i,q,n,p,'post');
	},
	
	/**
	 *	Alters the target entities innerHTML using AJAX.
	 *	Most commonly used to appear to navigate to a new
	 *	page by altering the central reservation.
	 *
	 *	u : URL to navigate.
	 *	t : Target Container ( defalts to : SAF_BODY )
	 *	i : iFrame ( back button initiated )
	 *	q : quiet - no loader.. - and remove the calling object..
	 *	n : no return value (for flash... grr.. )
	 *	m : method ( use saf.post(u,t,i,q,n) for shortcut )
	 *	p : parameters... to post
	 */
	navigate: function(u,t,i,q,n,p,m){
		opts = {};
		if ( !u ) { // Reload mode ( need to organise the prefix a bit better )
			u = '/ajax';
			u += document.location.pathname;
			u += document.location.search; 
			this.set_click_title('Updating...');
		}
		if ( t && !Object.isElement(t) ) {
			// Now read in options.. 
			opts = t;
			// Fix the target.. 
			if ( opts.target ) {
				t = opts.target;
			}
			if ( opts.quiet ) {
				q = true;
			}
		}
		if ( t && $(t) ) {
			this.target = t;
		} else if ( $(this.default_block) ) {
			this.target = $(this.default_block);
		} else if ( $('panel-b') ) {
			this.target = $('panel-b');
		} else {
			return false;
		}
		
		/**
		 * 	Scroll to the DIV ( with a little offset )
		 */
		bDoScrollTo = Object.isUndefined( opts.scroll ) || opts.scroll;
		if ( bDoScrollTo && this.options.get('scrollToOffset') && this.target  ) {
			if ( typeof Effect != 'undefined' ) {
				if ( this._effectScrollTo ) {
					this._effectScrollTo.cancel();
				}
				this._effectScrollTo = Effect.ScrollTo( this.target, {
					offset	: this.options.get('scrollToOffset')
				});
			} else {
				this.target.scrollTo();
			}
		}
		
		if ( !q ) {
			this.loader();
		} else {
			if ( $(q) && $(q).id ){
				$(q).remove();
			}
		}
		
		
		m = m ? m : 'get';
		
		
		if ( this.body = $(this.target) ){
			this.ajax = new Ajax.Request(
				u,
				{
					method 		: m,
					parameters	: p,
					evalScripts	: true,
					override	: true,
					onComplete 	: this.on_complete.bind(this, $(this.target))
				}
			);
			/*
			this.ajax = new Ajax.Updater(
				this.body,
				u,
				{
					method 		: m,
					parameters	: p,
					evalScripts	: true,
					override	: true,
					onComplete 	: this.on_complete.bind(this)
				}
			);
			*/
			this.message( Ajax.activeRequestCount + ' ajax requests running...' );
			// Back Buttonism..
			if ( !i ) {
				window.status = "BB:" +u;
				this.set_bb(u);
			}
		} else {
			this.error('Cannot locate suitable container : ' + t);
		}
		if ( n ) {
			// shh... 
		} else {
			return false;
		}
	},
	
	reload: function( sElement ){
		// console.log(sElement);
		if ( ( o = $(sElement) ) || ( o = $('e-'+sElement) ) ) {
			sBase 	= '/reload:' + sElement;
			sPath 	= document.location.pathname;
			sSearch = document.location.search; 
			// Combine..
			sUrl = sBase + sPath + sSearch;
			this.set_click_title('Updating...');
			this.navigate( sUrl, o );
		} else {
			//alert( "Can't find " + sElement + " or e-" +sElement );
		}
	},
	
	
	
	
	iFramePostForm: function( oForm, aArgs ){
		if ( true ){ // aArgs.fileUpload ( now 
			// alert('Running fileUploads through an iFrame..');
			// Build a blank iFrame..
			var oTmpIFrame = $(document.createElement("iframe"));
				oTmpIFrame.src 		= 'about:blank';
				oTmpIFrame.name		= 'oTmpIFrame_' + Math.round( Math.random()*1000000 );
				oTmpIFrame.addClassName('offScreen');
			$(document.body).insert({top:oTmpIFrame});
			// Set-up the form to submit to the correct URL into the iFrame..
			oForm.target = oTmpIFrame.name;
			oForm.action = aArgs.action;
			// alert('Submitting form ('+oForm.action+') to: ' + oTmpIFrame.name );
			// Observe the iFrame for when it re-loads..
			oTmpIFrame.observe('load',function(event){
				var element = Event.element(event);
				if ( oIFrameDoc = (element.contentWindow || element.contentDocument) ) {
					if ( sSource = oIFrameDoc.document.body.innerHTML ) {
						if ( aArgs.targetElement ) {
							$(aArgs.targetElement).innerHTML = sSource;
						}
					}
				}
				$(oTmpIFrame).remove();
			});
			// Submit the form..
			oForm.submit();
		} else {
			alert('No files?');
			return false;
		}
	},
	
	/**
	 *	Toggles the given item in a user's Favorites.
	 *	
	 *	i : Item ID
	 *	t : Target Object ( usually the causal link )
	 *	m : Mode ( for the php to work out the return value ) 
	 *	u : Base URI ( defaults to '/r/x/saf/fav/' ) 
	 */
	favorites: function(i,t,m,u){
		u  	= u || '/saf/fav/';
		p	= 'i='+i+'&m='+m;
		this.ajax = new Ajax.Updater(
			t,
			u,
			{
				method : 'get',
				parameters : p,
				evalScripts: true
			}
		);
	},
	
	
	set_bb: function(u){
		if ( this.iframe = $('SAF_IFRAME') ){
			var now = new Date();
			this.iframe.src = '/r/x/saf/bb.php?u='+escape(u)+'&t='+now.valueOf();
		} 
	},
	
	on_complete : function( oTarget, response ){
		// console.log(response);
		// console.log(oTarget);
		/**
		 * 	Emulate the Ajax.Updater() functionality plus.. 
		 */
		if ( response.responseText.indexOf('id="'+this.body.id+'"') != -1 ) {
			Element.replace( oTarget , response.responseText );
		} else {
			Element.update( oTarget , response.responseText );
		}
		// as we were..
		requests = Ajax.activeRequestCount - 1; // <<-- onComplete seems to fire before the counter is reduced.
		msg = ( requests ) ? requests + ' requests running...' : 'Complete';
		saf.message( msg );
		if ( response.headerJSON ) {
			if ( sNewTitle = response.headerJSON.set_title_tag ) {
				document.title = sNewTitle;
			}
		}
		if ( typeof(Lightview) != 'undefined' ){
			Lightview.updateViews();
		}
		if ( this.userCallbacks && this.userCallbacks.on_complete ) {
			this.userCallbacks.on_complete();
		}
	},
	
	addCallback : function ( callbacks ){
		this.userCallbacks = callbacks;
	},
	
	message: function ( msg ) {
		window.defaultStatus = msg;
	},
	
	error: function(msg){
		window.status = '[SAF:Error] ' + msg;
	},
	
	loaderStack : [],
	
	loader: function( targetText ){
	
		if ( ( id = this.loaderStack[this.target.id] ) && $('saf_loader_'+id) ) {
			$('saf_loader_'+id).remove();
			this.loaderStack[this.target.id] = null;
		}
		
		if ( this.target ) {
			var id = Math.round( Math.random() * 1000000 );
			var txt = this._click_title || 'Loading...';
			var html = '<div class="saf_loader" onclick="return false;" id="saf_loader_'+id+'"><span class="inner" id="saf_loader_msg_'+id+'"><span class="msg">&#187; '+txt+'</span></span><div class="transbg" id="saf_loader_bg_'+id+'"></div></div>';
			if ( Prototype.Version.substr(0,3) == '1.6' ) {
				$(this.target).insert( { top : html } );
				$('saf_loader_bg_'+id).clonePosition( this.target );
			} else {
				new Insertion.Bottom($(this.target), html ); 
				// ~~ 
				Position.clone( this.target, $('saf_loader_'+id) );
				Position.clone( this.target, $('saf_loader_bg_'+id) );
				Position.clone( this.target, $('saf_loader_msg_'+id) );
			}
		}
		
		this.loaderStack[this.target.id] = id;
		
	},
	
	event_hooks: function( event ){
		if ( event && Event.element(event) && Event.element(event).tagName ) {
			if ( ( ele = Event.element(event) ) && ele.title ){
				saf.set_click_title( ele.title ); // <<-- why does 'this' not work?
			} else if ( ( ele = Event.element(event) ) && ele.loadmessage ){
				saf.set_click_title( ele.loadmessage ); // <<-- why does 'this' not work?
			} else if ( ( ele = Event.element(event) ) && ( ele.tagName.toUpperCase() == 'A' ) && ( ele.innerText ) ){
				saf.set_click_title( ele.innerText );
			} else if ( ( ele = Event.findElement(event,'a') ) && ( ele != document ) && ( ele.title || ele.innerText ) ) {
				if ( ele.title ) {
					saf.set_click_title( ele.title );
				} else {
					saf.set_click_title( ele.innerText );
				}
			} else {
				saf.set_click_title();
			}
		} else {
			Event.observe( document.body, 'mousedown', saf.event_hooks );
		}
	},
	
	_setup_event_hooks: function (){
		Event.observe( document.body, 'mousedown', saf.event_hooks );
	},
	
	set_click_title: function ( sTitle, bWrap ){
		if ( bWrap ) {
			this._click_title = ( sTitle ) ? 'Loading ' + sTitle + '...' : 'Loading...';
		} else {
			this._click_title = ( sTitle ) ? sTitle : 'Loading...';
		}
	},
	
	automate: function ( mElement, oOptions ){
		/**
		 * 	Accept a single element or an array (from $$() of elements)
		 */
		aElements = false;
		if ( Object.isElement(mElement) ) {
			aElements = $A([mElement]);
		} else if ( Object.isArray(mElement) ) {
			aElements = mElement;
		} else {
			//alert("Error: Can't automate: " + mElement);
		}
		if ( aElements ) {
			aElements.each(function(oElement){
				//alert("Setting up automation of:\n\n" + oElement );
				oElement.__saf_auto_options = oOptions;
				Event.observe( oElement, 'click', this._auto_link.bind( oElement ) );
				Event.observe( oElement, 'submit', this._auto_submit.bind( oElement ) );
			}.bind(this));
		} else {
			//alert('Hmm...');
		}
	},
	
	fireEvent: function (element,event){
	    if (document.createEventObject){
	        // dispatch for IE
	        var evt = document.createEventObject();
	        return element.fireEvent('on'+event,evt);
	    }
	    else{
	        // dispatch for firefox + others
	        var evt = document.createEvent("HTMLEvents");
	        evt.initEvent(event, true, true ); // event type,bubbling,cancelable
	        return !element.dispatchEvent(evt);
	    }
	},
	
	_auto_submit: function ( event ){
		Event.stop(event);
		if ( ( ele = Event.element(event) ) && ( ele.tagName.toLowerCase() == 'form' ) ){
			// prefix...
			if ( ele.attributes && ele.attributes.ajaxctrl ){
				prefix = ele.attributes.ajaxctrl.value;
			} else if ( this.__saf_auto_options && this.__saf_auto_options.prefix ) {
				prefix = this.__saf_auto_options.prefix;
			} else {
				prefix = 'ajax';
			}
			// title...
			if ( ele.title ) {
				saf.set_click_title( ele.title, 1  );
			} else {
				saf.set_click_title( 'Please wait...', 1 );
			}
			// target...
			if ( this.__saf_auto_options && this.__saf_auto_options.target ) {
				target = this.__saf_auto_options.target;
			} else if ( ele.attributes && ele.attributes.ajax_target ){
				target = ele.attributes.ajax_target.value;
				if ( target == 'self' ) {
					target = ele;
				} else if ( target == 'parent' ) {
					target = ele.up();
				}
			} else {
				target = false;
			}
			// quietness
			if ( ele.attributes && ele.attributes.quiet ) {
				quiet = true;
			} else {
				quiet = false;
			}
			// go!!
			sAction = $(ele).action ? $(ele).action : document.location.pathname;
			sUri 	= sAction.sub( /http\:\/\/(.*?)\/(.*)\/?/ ,'#{2}');
			sUri	= sUri.substr(0,1) == '/' ? sUri.substr(1) : sUri; // Strip leading slash..
			sUri 	= '/'+prefix+'/'+sUri;
			/**
			 *	Check for FCKEditor..
			 */
			var __fck = ( typeof FCKeditorAPI != 'undefined' );
			/**
			 *	Check for FILE elements ( that have some new values.. )
			 */
			var fileUploads = ele.getInputs('file');
			var bUploads	= false;
			if ( fileUploads.length ) {
				fileUploads.each(function(element){
					if ( element.value ) {
						bUploads = true;
					}
				});
			}
			
			if ( bUploads || __fck ) {
				/* 
				saf.iFramePostForm(ele, {
					'fileUpload'	: bUploads,
					'action'		: sUri,
					'targetElement'	: target
				});
				 */
				ele.submit();
			} else {
				// alert('Ajax POST will work...');
				saf.post( sUri, target, false, quiet, false, ele.serialize() );
			}
			Event.stop( event );
		} else {
			alert('Error: Could not find form element from event.');
		}
		Event.stop(event);
	},
	
	_auto_link: function ( event ) {
		if ( event.iStop ) {
			return;
		}
		if ( ele = Event.element(event) ){
			if ( ( ele.tagName.toLowerCase() == 'a' ) || ( ele = ele.up('a') ) ) {
				
				if ( event.shiftKey || event.ctrlKey || event.altKey ) {
					// Leave to proceed as normal.. no ajaxification.. 
					
					if ( event.altKey ) {
						document.location.href = ele.href;
					} else {
						return true;
					}
				} else if ( ele.target ) {
					// Leave to proceed as normal.. no ajaxification.. 
					// alert('Targeted click...');
					return true;
				} else if ( $(ele).hasAttribute('noajax') || $(ele).hasClassName('lightview') ) {
					// Leave to proceed as normal.. no ajaxification..  
					return true;
				} else {
					// alert('Looking good.. ');
					if ( !ele.onclick && ele.href ) {
						sDomain = ele.href.sub( /http\:\/\/(.*?)\/(.*)/ ,'#{1}');
						sUri 	= ele.href.sub( /http\:\/\/(.*?)\/(.*)/ ,'#{2}');
						if ( sDomain && sDomain != document.location.hostname ){
							// Cross Domain Click..
							// alert('Cross domain.. ');
							return true;
						} else {
							//
							if ( ele.attributes && ele.attributes.ajaxctrl ){
								prefix = ele.attributes.ajaxctrl.value;
							} else if ( this.__saf_auto_options && this.__saf_auto_options.prefix ) {
								prefix = this.__saf_auto_options.prefix;
							} else {
								prefix = 'ajax';
							}
							// alert('Prefix:' + prefix);
							// 
							if ( ele.title ) {
								saf.set_click_title( ele.title, 1  );
							} else {
								saf.set_click_title( ele.innerText, 1 );
							}
							// target...
							if ( ele.attributes && ele.attributes.ajax_target ){
								target = ele.attributes.ajax_target.value;
								if ( target == 'self' ) {
									target = ele;
								} else if ( target == 'parent' ) {
									target = ele.up();
								}
							} else {
								target = false;
							}
							
							sUri = '/'+prefix+'/'+sUri;
							
							Event.stop(event);
							if ( $(ele).hasClassName('saf-lightview') ) {
								saf.navigateLightView(sUri);
							} else {
								saf.navigate(sUri,target);
							}
						}
					} else if ( ele.onclick ) {
						// Onclick will take care of stuff..
						Event.stop(event);
					} else {
						alert('Unknown element arguments...');
					}
				}
			} else {
				// alert('Not a link...');
			}
		} else {
			// alert('No event element...');
		}
	},
	
	navigateLightView : function ( sUrl ){
		Lightview.show({
			href: sUrl,
			rel: 'ajax',
			// title: this._click_title,
			// caption: 'Enter your username and password to login',
			options: {
				autosize: true,
				topclose: true,
				ajax: {
					method: 'get',
					evalScripts: true,
					onComplete: function(){ 
						
					}
				}
			}
		});
		return false;
	},
	
	
	log : function ( oArgs ){
		var logTmp = new Ajax.Request(
			'/r/x/event/',
			{
				method		: 'get',
				parameters 	: oArgs
			}
		);
	},
	
	
	leachGA : function(){
		if ( $('__saf_ctrlFrame') ) {
			$('__saf_ctrlFrame').src = pageTracker._getLinkerUrl("/r/x/ga/leach.php");
		}
	}
	
	
};

var saf = new SpiritAjaxFramework({
	scrollToOffset : -35
});


Event.observe( window, 'load', saf._setup_event_hooks );
// window.setTimeout( saf.event_hooks, 1000 );