// 
// Marino Software
// Dave O'Keeffe
// 
// (All times are in seconds.)
// var myAIB = new mSlider(
// 	<Div ID>,													// * The ID
// 	{																	//
// 		content: [MIXED],								// * JavaScript array of URLs for Content
// 		scrollSize: 400,								// * Distance to be scrolled
// 		aspect: 'horizontal',						//	 Scroll Aspect (HORIZONTAL|vertical)
// 		direction: 'tlbr',							//	 Scroll Direction (TLBR|brtl)  ie: moving Top Left to Bottom Right
// 		leadInMorphStyle:'opacity:.5',	//	 Style declaration to morph to during animation lead in (blank = no lead in)
// 		leadInDuration: 0.2,						//	 Duration of lead in animation
// 		leadInDelay: 0,									//	 Delay before starting lead in animation
// 		transitionDuration: .2,					//	 Duration of movement animation (0=no animation)
// 		transitionDelay: 0,							//	 Delay before starting movement animation
// 		leadOutMorphStyle:'opacity:1',	//	 Style declaration to morph to during animation lead out (blank = no lead out)
// 		leadOutDuration: 0.2,						//	 Duration of lead out animation
// 		leadOutDelay: 0,								//	 Delay before starting lead out animation
// 		periodical: 5										//	 Delay before automatically getting the next element (Default=0) (0=off)
// 	}
// 
// Use mySlider.getPreviousElement(); and mySlider.getNextElement(); to scroll
// ie: 
// <input type="button" class="btn" value="Next" onclick="javascript:mySlider.getPreviousElement();" />
// or:
// <a href="#" onclick="javascript:mySlider.getPreviousElement();return false;"></a>
// 
// When periodicals are used, the mouseover event stops the periodical and mouseover restarts it.
//
// Required styles are in:
// mSlider.css
// 
// DO NOT MODIFY THIS JS FILE OR THE CSS FILE!  Any modifcations should be done via overrides.
// 
// Styles are applied as follows:
//
// 

if (typeof Prototype == 'undefined' || parseFloat(Prototype.Version.substring(0, 3)) < 1.6)
  throw 'mSlider requires Prototype version 1.6 or greater.';

var mSliders = [];

var mSlider = Class.create({
	Version: '0.1',

	initialize: function(container, options) {
		this.busy = true;
		mSliders.push(this);
		this.index = mSliders.length-1;
		this.slideCount = 0;

		this.container = $(container);
		this.container.addClassName('mSliderContainer');

		this.slider = new Element('div').addClassName('mSliderWrapper');
		this.container.insert( this.slider );

		this.panels = new Array();
		this.panels.push( new Element('div').addClassName('mSliderElement') );
		this.panels.push( new Element('div').addClassName('mSliderElement') );
		this.panels.push( new Element('div').addClassName('mSliderElement') );
		this.slider.insert(this.panels[0]);
		this.slider.insert(this.panels[1]);
		this.slider.insert(this.panels[2]);

		this.options = $H(options || {});
		this.aspect = this.options.get('aspect');
		this.scrollDirection = (this.options.get('direction') == "tlbr" ? -1 : 1);
		this.scrollSize = (this.options.get('scrollSize') || this.slider.down('div').getDimensions()[this.dimAttribute]);

		this.content = (this.options.get('content') || []);
		this.contentIndex = (this.options.get('contentIndex') || 0);
		if(this.contentIndex >= this.content.length)
		{
			this.contentIndex = this.content.length;
		}

		this.transitionDuration = this.options.get('transitionDuration')!=null?this.options.get('transitionDuration'):.4;
		this.transitionDelay = this.options.get('transitionDelay')!=null?this.options.get('transitionDelay'):0;

		this.leadInMorphStyle = this.options.get('leadInMorphStyle')!=null?this.options.get('leadInMorphStyle'):'opacity:0.5';
		this.leadInDuration = this.options.get('leadInDuration')!=null?this.options.get('leadInDuration'):0.2;
		this.leadInDelay = this.options.get('leadInDelay')!=null?this.options.get('leadInDelay'):0;

		this.leadOutMorphStyle = this.options.get('leadOutMorphStyle')!=null?this.options.get('leadOutMorphStyle'):'opacity:1';
		this.leadOutDuration = this.options.get('leadOutDuration')!=null?this.options.get('leadOutDuration'):0.2;
		this.leadOutDelay = this.options.get('leadOutDelay')!=null?this.options.get('leadOutDelay'):0;
		
		this.periodical = this.options.get('periodical')!=null?this.options.get('periodical'):0;
		
		this.onAjaxStart = this.options.get('onAjaxStart')||Prototype.emptyFunction;
		this.onAjaxStop = this.options.get('onAjaxStop')||Prototype.emptyFunction;
		
		this.dbg("scrollSize: "+this.scrollSize);
		
		this.posAttribute = (this.aspect == "horizontal" ? "left" : "top");
		this.dimAttribute = (this.aspect == "horizontal" ? "width" : "height");
		this.nextContent = "";
		
		if(this.aspect == 'horizontal')
		{
			this.slider.addClassName('mSliderHWrapper');
		}
		
		this.position = (this.scrollSize * -1); // jumps to the center element
		this.slider.style[this.posAttribute] = this.position + 'px';
		
		// get first content
		this.DisplayContent( this.contentIndex );
		this.busy = false;
		
		if(this.periodical!=0)
		{
			this.cb_StopPeriodical = this._stopPeriodical.bind(this);
			this.cb_StartPeriodical = this._startPeriodical.bind(this);

			this._startPeriodical();
			this.container.observe('mouseover', this.cb_StopPeriodical);
			this.container.observe('mouseout', this.cb_StartPeriodical);
		}
		return this;
	},
	
  destroy: function($super) {
	  if(this.periodical!=0)
	  {
		  this._stopPeriodical();
			this.container.stopObserving('mouseover', this.cb_StopPeriodical);
			this.container.stopObserving('mouseout', this.cb_StartPeriodical);
	  }
	  this.container.removeClassName('mSliderContainer');
	  this.container.down().remove();
  },

	DisplayContent: function(idx) {
		this.dbg("DisplayContent()");
		
		if(this.content[ idx ].url != null)
		{
			// ajax request
			if(this.slideCount == 0)
			{
				this.cb_HandleResponse = this._handleInitialResponse.bind(this);
			} else {
				this.cb_HandleResponse = this._handleResponse.bind(this);
			}
			this.dbg("new AjaxRequest()");
			this.onAjaxStart();
			new Ajax.Request(this.content[ idx ].url,
				{
					method: this.content[ idx ].method || 'get',
					onSuccess: this.cb_HandleResponse,
					onFailure: function(transport) {
						this.busy = false;
						alert("Ajax Request Failed!");
					}
				}
			);
			return;
		}
		
		this.nextContent = null;
		if(this.content[ idx ].text != null)
		{
			this.dbg("Plain text slider content");
			this.nextContent = this.content[ idx ].text;
			if(this.nextContent != null)
			{
				if(this.slideCount == 0) {
					this._leadOut();
				} else {
					this._leadIn();
				}
			} else {
				this.busy = false;
				alert("Unknown Data Type!");
			}
		}
		else if(this.content[ idx ].dom != null)
		{
			this.dbg("Dom slider content");
			this.nextContent = this.content[ idx ].dom.innerHTML;
			if(this.nextContent != null)
			{
				if(this.slideCount == 0) {
					this._leadOut();
				} else {
					this._leadIn();
				}
			} else {
				this.busy = false;
				alert("Unknown Data Type!");
			}
		}
		else if(this.content[ idx ].img != null)
		{
			this.dbg("Image slider content");
			// include an onLoad function to ensure the image has loaded before we switch to it
			this.nextContent = "<img src=\""+this.content[ idx ].img+"\"/>";
			if(this.nextContent != null)
			{
				if(this.slideCount == 0) {
					this.cb_Animate = this._leadOut.bind(this);
				} else {
					this.cb_Animate = this._leadIn.bind(this);
				}
				this.onAjaxStart();
				this.panels[0].update( "<img onLoad='javascript:mSliders["+this.index+"].cb_Animate();mSliders["+this.index+"].onAjaxStop();' src=\""+this.content[ idx ].img+"\"/>" );
			} else {
				this.busy = false;
				alert("Unknown Data Type!");
			}
			
		}
		else
		{
		    this.busy = false;
		    alert("Unknown Data Type!");
		}
	},
	
	_handleInitialResponse: function(transport) {
		this.dbg("_handleInitialResponse()");
		this.nextContent = transport.responseText;
		this.onAjaxStop();
		this._leadOut();
	},
	
	_handleResponse: function(transport) {
		this.dbg("_handleResponse()");
		this.nextContent = transport.responseText;
		this.onAjaxStop();
		this._leadIn();
	},
	
	getNextElement: function(pe) {
		if(this.busy) return;
		if( pe==null && this.periodical != 0 ) { this._restartPeriodical(); }
		this.busy = true;
		this.contentIndex = this.contentIndex+1;
		this.dbg("Content Index: "+this.contentIndex);
		this.dbg("Content Length: "+this.content.length);
		if(this.contentIndex >= this.content.length) this.contentIndex=0;
		this._nextScrollDirection = this.scrollDirection;

		// this.cb_HandleResponse = this._handleResponse.bind(this);
		this.DisplayContent( this.contentIndex, this._handleResponse.bind(this) );
	},
	
	getPreviousElement: function(pe) {
		if(this.busy) return;
		if( pe==null && this.periodical != 0 ) { this._restartPeriodical(); }
		this.busy = true;
		this.contentIndex = this.contentIndex-1;
		if(this.contentIndex < 0) this.contentIndex=this.content.length-1;
		this._nextScrollDirection = this.scrollDirection * -1;

		// this.cb_HandleResponse = this._handleResponse.bind(this);
		this.DisplayContent( this.contentIndex, this._handleResponse.bind(this) );
	},
	
	_leadIn: function() {
		this.dbg("_leadIn()");
		// change side panels to what we're going to scroll to.
		this.panels[0].update( this.nextContent );
		this.panels[2].update( this.nextContent );


		// decide on final end position
		this.animationEndPos = this.position+(this.scrollSize * this._nextScrollDirection);
		
		if(this.leadInMorphStyle != '')
		{
			this.cb_Transition = this._transition.bind(this);
			// morph font color to background on center
			this.slider.morph(this.leadInMorphStyle, {
						duration: this.leadInDuration,
						delay: this.leadInDelay,
						afterFinish: this.cb_Transition
			});
		} else {
			this._transition();
		}
	},
	
	_transition: function(){
		this.dbg("_transition()");

		if(this.transitionDuration > 0 || this.transitionDelay > 0)
		{
			this.cb_LeadOut = this._leadOut.bind(this);
			// morph position
			this.slider.morph(this.posAttribute + ": " + this.animationEndPos + "px", {
					duration: this.transitionDuration,
					delay: this.transitionDelay,
					afterFinish: this.cb_LeadOut
				}
			);
		}
		else
		{
			this.slider.style[this.posAttribute] = this.animationEndPos + "px";
			this._leadOut();
		}
	},
	
	_leadOut: function() {
		this.dbg("_leadOut()");
		
		if(this.leadOutMorphStyle != '')
		{
			this.cb_AnimationComplete = this._animationComplete.bind(this);
			// morph background color back to what it should be.
			this.slider.morph(this.leadOutMorphStyle, {
				duration: this.leadOutDuration,
				delay: this.leadOutDelay,
				afterFinish: this.cb_AnimationComplete
			});
		} else {
			this._animationComplete();
		}
	},
	
	_animationComplete: function() {
		// update center panel
		this.panels[1].update( this.nextContent );

		// snap back to center panel so we're ready for next change.
		this.position = (this.scrollSize * -1);
		this.slider.style[this.posAttribute] = this.position + 'px';

		this.dbg("Animation Complete");
		this.slideCount++;
		this.busy = false;
	},
	
	_stopPeriodical: function()
	{
		this.dbg("Stopping PeridicalExecuter");
		this.periodicalExecuter.stop();
	},
	
	_startPeriodical: function()
	{
		this.dbg("Starting PeridicalExecuter");
		this.cb_Periodical = this.getNextElement.bind(this);
		this.periodicalExecuter = new PeriodicalExecuter( this.cb_Periodical, this.periodical);
	},
	
	_restartPeriodical: function()
	{
		this._stopPeriodical();
		this._startPeriodical();
	},
	
	dbg: function(s) {
		// console.log(this.index+"::"+s);
	}
});
