/*
* Crossfade
* Version 4.1 30/03/2007
* 
* Copyright (c) 2007 Millstream Web Software http://www.millstream.com.au
* 
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* 
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* 
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
* * 
*/
var Crossfade = Class.create();
Crossfade.prototype = {
	loaded : false,
	initialize : function(elm, options) {
		var me = this, next, prev;
		this.elm = $(elm);
		this.counter = 0;
		this.prevSlide = null;
		this.moveDir = 1;
		this.movePlay = 1;
		this.seekSlide = 0;
		var t_opt = {};
		for(t in Crossfade.Transition) {
			var trans = Crossfade.Transition[t];
			if(trans.className && this.elm.hasClassName(trans.className)) {
				t_opt = {transition:trans};
				break;
			}
		}
		this.options = Object.extend(Object.clone(Crossfade.defaults),Object.extend(options || {},t_opt));
		this.options.interval = Math.max(2,this.options.interval);
		this.moveSpeed = this.options.interval;
		this.elm.makePositioned();
		this.slides = this.elm.immediateDescendants();
		if(this.options.random || this.elm.hasClassName(this.options.randomClassName)){
			this.slides.sort(function(a,b){
				return me.rndm(-1,1);
			});
		}
		if(this.elm.id) {
			next = $(this.elm.id + '-next');
			prev = $(this.elm.id + '-previous');
			if(next) { Event.observe(next, 'click', this.next.bind(this)); }
			if(prev) { Event.observe(prev, 'click', this.previous.bind(this)); }
		}
		
		this.loadSlide(this.slides[0],function() {
			me.options.transition.prepare(me);
		});
		this.loadSlide(this.slides[1]);
		
		if(this.options.autoStart) { setTimeout(this.start.bind(this),this.rndm((this.options.interval-1)*1000,(this.options.interval+1)*1000)); }
	},
	start : function() {
		this.ready = true;
		this.slideTimeTicker = this.moveSpeed;
		this.ticker();
		if (!this.timer) this.timer = new PeriodicalExecuter(this.cycle.bind(this), 1);
	},
	stop : function() {
		this.options.transition.cancel(this);
		this.timer.stop(); 
	},
	next : function(){
		this.slideTimeTicker = 0;
		this.moveDir = 1;
	},
	previous : function() {
		this.slideTimeTicker = 0;
		this.moveDir = -1;
	},
	cycle : function() {
		if(this.movePlay !== 1) { return; }
		if(!this.ready) { return; }
		if(!this.options.transition.ready) { return; }
		if (this.slideTimeTicker > 0)
		{
			this.slideTimeTicker--;
		}
		if (this.slideTimeTicker < 0) { 
			this.slideTimeTicker = 0;
		}
		this.ticker();
		if (this.slideTimeTicker > 0) { 
			return; 
		}
		this.ready = false;
		dir = (this.moveDir == -1) ? -1 : 1;
		var me = this, prevSlide, nextSlide, opt, fade;
		prevSlide = this.slides[this.counter];
		this.counter = this.loopCount(this.counter + dir);
		if((this.counter == 0) && (dir == 1)){
			this.loaded = true;
		}
		nextSlide = this.slides[this.counter];
		this.loadSlide(nextSlide, me.options.transition.cycle(prevSlide, nextSlide, me));
		if(!this.loaded) {
			this.loadSlide(this.slides[this.loopCount(this.counter+1)]);
		}
	},
	ticker : function()
	{
		var slideTicker = document.getElementById('slideTicker');
		if (slideTicker)
		{
			slideTicker.innerHTML = this.slideTimeTicker;
		}
	},
	adjust : function(dir, speed, play) {
		if (this.moveDir !== dir)
		{
			this.moveDir = dir;			// 1 = Forward -1 = Backward
			this.slideTimeTicker = 0;
		}
		if (this.moveSpeed !== speed)
		{
			this.slideTimeTicker = this.slideTimeTicker - this.moveSpeed + speed;
			this.moveSpeed = speed;
		}
		this.movePlay = play;		// 1 = Run 0 = Stop
	},
	seek : function(slide)
	{
		this.seekSlide = slide;
	},
	loadSlide : function(slide, onload){
		var loaders = [], me = this, img, pnode, onloadFunction;
		onload = typeof onload === 'function' ? onload : function(){};
		onloadFunction = function() {
				onload();
				me.ready = true;
			};
		slide = $(slide);
		loaders = Selector.findChildElements(slide,[this.options.imageLoadSelector]);
		if(loaders.length && loaders[0].href !== ''){
			img = document.createElement('img');
			img.className = 'loadimage';
			img.onload = onloadFunction;
			img.src = loaders[0].href;
			loaders[0].parentNode.replaceChild(img,loaders[0]);
		} else {
			loaders = [];
			loaders = Selector.findChildElements(slide, [this.options.ajaxLoadSelector]);
			if(loaders.length && loaders[0].href !== ''){
				new Ajax.Updater(slide, loaders[0].href, {method:'get',onComplete:onloadFunction});
			} else {
				onloadFunction();
			}
		}
	},
	loopCount : function(c){
		if(c >= this.slides.length){
			c = 0;
		} else if (c < 0) {
			c = this.slides.length - 1
		}
		return c;
	},
	rndm : function(min, max){
		return Math.floor(Math.random() * (max - min + 1) + min);
	},
	timer : null,effect : null,ready : false
};
Crossfade.Transition = {};
Crossfade.Transition.Switch = {
	className : 'transition-switch',
	cycle : function(prev, next, show) {
		show.slides.without(next).each(function(s){
			$(s).hide();
		})
		$(next).show();
	},
	cancel : function(show){},
	prepare : function(show){
		show.slides.each(function(s,i){
			$(s).setStyle({display:(i === 0 ? 'block' : 'none')});
		});	
	}
};
Crossfade.Transition.Crossfade = {
	className : 'transition-crossfade',
	cycle : function(prev, next, show) {
		var opt = show.options;
		show.effect = new Effect.Parallel([new Effect.Fade(prev ,{sync:true}),
			new Effect.Appear(next,{sync:true})],
			{duration: opt.duration, queue : 'Crossfade', afterFinish:function(){
				show.slides.without(next).each(function(s){
					$(s).setStyle({opacity:0});
				})
			}}
		);
	},
	cancel : function(show){
		if(show.effect) { show.effect.cancel(); }
	},
	prepare : function(show){
		show.slides.each(function(s,i){
			$(s).setStyle({opacity:(i === 0 ? 1 : 0),visibility:'visible'});
		});	
	}
};
Crossfade.Transition.FadeOutFadeIn = {
	className : 'transition-fadeoutfadein',
	cycle : function(prev, next, show) {
		var opt = show.options;
		show.effect = new Effect.Fade(prev ,{
			duration: opt.duration/2,
			afterFinish: function(){
				show.effect = new Effect.Appear(next,{duration: opt.duration/2});
				show.slides.without(next).each(function(s){
					$(s).setStyle({opacity:0});
				})
			}
		});
	},
	cancel : function(show){
		if(show.effect) { show.effect.cancel(); }
	},
	prepare : function(show){
		show.slides.each(function(s,i){
			$(s).setStyle({opacity:(i === 0 ? 1 : 0),visibility:'visible'});
		});	
	}
};
Effect.DoNothing = Class.create();
Object.extend(Object.extend(Effect.DoNothing.prototype, Effect.Base.prototype), {
	initialize: function() {
		this.start({duration: 0});
	},
	update: Prototype.emptyFunction
});
Crossfade.Transition.FadeOutResizeFadeIn = {
	className : 'transition-fadeoutresizefadein',
	cycle : function(prev, next, show) {
		var opt = show.options;
		this.ready = false;
		show.effect = new Effect.Fade(prev ,{
			duration: (opt.duration-1)/2,
			afterFinish: function(){
//				show.slides.without(next).each(function(s){ $(s).setStyle({opacity:0});});
				var slideDims = [next.getWidth(),next.getHeight()];
				// Move to the next (or previous) slide
				var loadimg = Selector.findChildElements(next,['img.loadimage']);
			    //loadimg[0] is coming in
				if(loadimg.length && loadimg[0].offsetWidth && loadimg[0].offsetHeight){
					slideDims[0] += slideDims[0] < loadimg[0].offsetWidth ? loadimg[0].offsetWidth : 0;
					slideDims[1] += slideDims[1] < loadimg[0].offsetHeight ? loadimg[0].offsetHeight : 0;
				}
				
				// JEG: Custom
				if (loadimg.length && (show.slides.length > 1))
				{
				    var slideCaption = document.getElementById('slideCaption');
				    if (slideCaption)
				    {
						// Set caption to the alt tag text
	                    for (var x = 0; x < loadimg[0].attributes.length; x++)
						{
	                        if (loadimg[0].attributes[x].nodeName.toLowerCase() == 'alt')
							{
	                            slideCaption.innerHTML = loadimg[0].attributes[x].nodeValue;
	                            break;
	                        }
	                    }
				    }
				    var slideThumbID = loadimg[0].id.replace('slide', 'thumb');
					var slideThumbImg = document.getElementById(slideThumbID);
					if (slideThumbImg)
					{
						slideThumbImg.className = 'thumbCurrent';
					}
					var previmg = Selector.findChildElements(prev,['img.loadimage']);
					if (previmg.length)
					{
						slideThumbID = previmg[0].id.replace('slide', 'thumb');
						slideThumbImg = document.getElementById(slideThumbID);
						if (slideThumbImg)
						{
							slideThumbImg.className = 'thumbNotCurrent';
						}
					}
					// Update prior and next
					var nextSlideIx = show.loopCount(show.counter + 1);
					var nextSlide = show.slides[nextSlideIx];					
					var nextImg = Selector.findChildElements(nextSlide,['img.loadimage']);
				    var nextThumbID = nextImg[0].id.replace('slide', 'thumb');
				    var nextAnchorID = nextImg[0].id.replace('slide', 'anchor');
                    var slideNext = document.getElementById('slideControl-next');
                    if (slideNext)
                    {
                        var aNext = document.getElementById(nextAnchorID);
                        if (aNext)
                        {
                            slideNext.href = aNext.href;
                            var iNext = document.getElementById(nextThumbID);
                            if (iNext)
                            {
		                        for (var x = 0; x < iNext.attributes.length; x++ ) {
		                            if (iNext.attributes[x].nodeName.toLowerCase() == 'alt' ) {
		                              slideNext.innerHTML = iNext.attributes[x].nodeValue;
		                              break;
		                            }
		                         }
		                     }
                        }
                    }
					var prevSlideIx = show.loopCount(show.counter - 1);
					var prevSlide = show.slides[prevSlideIx];					
					var prevImg = Selector.findChildElements(prevSlide,['img.loadimage']);
				    var prevThumbID = prevImg[0].id.replace('slide', 'thumb');
				    var prevAnchorID = prevImg[0].id.replace('slide', 'anchor');
					var slidePrev = document.getElementById('slideControl-previous');
					if (slidePrev)
					{
						var aPrev = document.getElementById(prevAnchorID);
						if (aPrev)
						{
							slidePrev.href = aPrev.href;
							var iPrev = document.getElementById(prevThumbID);
							if (iPrev)
							{
								for (var x = 0; x < iPrev.attributes.length; x++ ) {
									if (iPrev.attributes[x].nodeName.toLowerCase() == 'alt' ) {
									  slidePrev.innerHTML = iPrev.attributes[x].nodeValue;
									  break;
									}
								}
							}
						}
					}
                }
                // JEG: End
				var showDims = [show.elm.getWidth(),show.elm.getHeight()];
				var scale = [(showDims[0] > 0 && slideDims[0] > 0 ? slideDims[0]/showDims[0] : 1)*100,(showDims[1] > 0 && slideDims[1] > 0 ? slideDims[1]/showDims[1] : 1)*100];
				show.effect = new Effect.Parallel([
						(scale[0] === 100 ? new Effect.DoNothing() : new Effect.Scale(show.elm,scale[0],{sync:true,scaleY:false,scaleContent:false})),
						(scale[1] === 100 ? new Effect.DoNothing() : new Effect.Scale(show.elm,scale[1],{sync:true,scaleX:false,scaleContent:false}))
					],
					{
						duration: 1,
						queue : 'FadeOutResizeFadeIn',
						afterFinish: function(){
							show.effect = new Effect.Appear(next,{duration: (opt.duration-1)/2, afterFinish: 
								function(){ 
									show.options.transition.ready = true; 
											show.slideTimeTicker = show.moveSpeed + 1;
							} } );
						}
					}
				);
			}
		});
	},
	cancel : function(show){
		if(show.effect) { show.effect.cancel(); }
	},
	prepare : function(show){
		var slideDims = [$(show.slides[0]).getWidth(),$(show.slides[0]).getHeight()];
		show.elm.setStyle({width:slideDims[0]+'px', height:slideDims[1]+'px'});
		show.slides.each(function(s,i){
			$(s).setStyle({opacity:(i === 0 ? 1 : 0),visibility:'visible'});
		});	
	},
	ready : true
};
Crossfade.defaults = {
	autoLoad : true,
	autoStart : true,
	random : false,
	randomClassName : 'random',
	selectors : ['.crossfade'],
	imageLoadSelector : 'a.loadimage',
	ajaxLoadSelector : 'a.load',
	interval : 5,
	duration : 2,
	transition : Crossfade.Transition.Crossfade
};
Crossfade.setup = function(options) {
	Object.extend(Crossfade.defaults,options);
};
Crossfade.load = function() {
	if(Crossfade.defaults.autoLoad) {
		Crossfade.defaults.selectors.each(function(s){
			$$(s).each(function(c){
				return new Crossfade(c);
			});
		});
	}
};
if(window.FastInit) {
	FastInit.addOnLoad(Crossfade.load);
} else {
	Event.observe(window, 'load', Crossfade.load);
}
