/**
 *
 *	Requires W.Dom
 *	Requires W.Tween
 *	usages: var fader	= new W.Fader();
 *			var fader	= new W.Fader({nav: 'photonav', pause: 5000, loop: false, caption: true}).init_nav('photo', 'photos', 'div');
 *
 *		<div id="photos">
 *			<div class="photo">
 *				<img src="demos/images/galleries/vincent/28.jpg" alt="" width="398" height="389" border="0" title="Photo 1" />
 *			</div>
 *			<div class="photo">
 *				<img src="demos/images/galleries/vincent/29.jpg" alt="" width="398" height="389" border="0" title="Photo 2" />
 *			</div>
 *
 *			<ul id="photonav" class="clearfix"></ul>
 *		</div>
 *
 *		<script type="text/javascript" language="javascript">
 *			var fader	= new W.Fader({nav: 'photonav', auto: false}).init_nav('photo');
 *		</script>
 *
 *
 *	USAGE WHEN USING SWAPS
 *
 *	<div id="mn" class="page">
 *		<div class="content">
 *			<ul class="nav">
 *				<li><a href="#mn">Ostrander, Minnesota</a></li>
 *				<li><a href="#mo">Tipton, Missouri</a></li>
 *				<li><a href="#nd">Hankinson, North Dakota</a></li>
 *				<li><a href="#sd">Rapid City, South Dakota</a></li>
 *			</ul>
 *			
 *			<p></p>
 *		</div>
 *		
 *		<div class="photos" id="photos_mn">
 *			<div class="photo photo_mn"><img src="images/mn/01.jpg" alt="" width="475" height="477" border="0" /></div>
 *			<div class="photo photo_mn"><img src="images/mn/02.jpg" alt="" width="475" height="477" border="0" /></div>
 *			<div class="photo photo_mn"><img src="images/mn/03.jpg" alt="" width="475" height="477" border="0" /></div>
 *			<div class="photo photo_mn"><img src="images/mn/04.jpg" alt="" width="475" height="477" border="0" /></div>
 *			<div class="photo photo_mn"><img src="images/mn/05.jpg" alt="" width="475" height="477" border="0" /></div>
 *			<div class="photo photo_mn"><img src="images/mn/06.jpg" alt="" width="475" height="477" border="0" /></div>
 *			
 *			<ul class="photonav" id="photonav_mn"></ul>
 *		</div>
 *	</div>
 *	
 *	<script type="text/javascript" language="javascript">
 *	// <![CDATA[
 *		var pages = new W.Swap();
 *		pages.select(pages.find('home'));
 *		var fader_mn	= new W.Fader({nav: 'photonav_mn', auto: false, swap: pages}).init_nav('photo_mn');
 *		var fader_mo	= new W.Fader({nav: 'photonav_mo', auto: false, swap: pages}).init_nav('photo_mo');
 *		var fader_nd	= new W.Fader({nav: 'photonav_nd', auto: false, swap: pages}).init_nav('photo_nd');
 *		var fader_sd	= new W.Fader({nav: 'photonav_sd', auto: false, swap: pages}).init_nav('photo_sd');
 *	// ]]>
 *	</script>
 *
 *	Note: Captions are added dynamically because they need to be in the image's containing element
 *
 *	TODO:
 *	1. Change crossfade, so that images are absolutely positioned to be stacked on top of eachother, and it fades 1 image, but the 2nd image is already visible
 *	   e.g. image 1 going to image 2, both are visible, and image 1 fades to reveal image 2. Or image 2 going to image 1, image 2 stays visible and image 1
 *	   fades in
 *	2. Next and Previous should refer to jump so that all logic for switching photos is in one place - plus next and previous don't really work if loop is false
 *	3. Check if next image is ready when clicking on image or using arrows - change next and previous to verify
 *	4. Automatically create captions if title attribute is present?
 *
 */
W.Fader = function(param)
{
	this.init(param);
};


W.Fader.prototype = {


	photos			: null,			// array of photos - images are stored starting at 1, index 0 is not used
	index			: 1,			// photo this is currently visible
	prev_index		: 1,			// photo this is currently fading out
	tween			: null,			// reference to object running the opacity animation
	timer			: null,			// reference to timer for the next fade
	duration		: 7,			// how long the fade lasts
	_pause			: 3000,			// amount of time before photo fades out
	loop			: true,			// loop to the beginning after last photo?
	auto			: true,			// auto advance to the next photo?
	nav				: null,			// use a nav for photos?
	crossfade		: false,		// fade out and in at the same time?
	caption			: false,		// create captions?
	class_name		: 'photo',		// class name for divs containing each image
	swap			: false,		// reference to W.Swap
	click_advance	: true,			// user can click on a photo to advance to the next photo
	

	init : function(param)
	{
		// set param
		if (param) {
			if (param.duration !== undefined) { this.duration = param.duration; }
			if (param.pause !== undefined) { this._pause = param.pause; }
			if (param.loop !== undefined) { this.loop = param.loop; }
			if (param.auto !== undefined) { this.auto = param.auto; }
			if (param.nav !== undefined) { this.nav = W.$(param.nav); }
			if (param.caption !== undefined) { this.caption	= param.caption; }
			if (param.swap !== undefined) { this.swap = param.swap; }
			if (param.crossfade !== undefined) { this.crossfade = param.crossfade; }
			if (param.click_advance !== undefined) { this.click_advance = param.click_advance; }
		}
	
		this.photos = [];
		this.tween	= {};
		
		var obj	= this;
		//W.Event.add(document, 'keyup', function(e) { obj.key_nav(e); });
		
		W.Event.add(this);
		
		//if (this.nav) this.init_nav();
	},
	
	
	
	init_nav : function(class_name, node, tag)
	{
		this.class_name	= class_name;
		
		var photos = W.Dom.getElementsByClassName(class_name, node, tag);
		var img;
		var zindex	= 1200;
		
		this.add_jump('&lt; prev', 'previous');
		
		for (var i = 0, max = photos.length; i < max; ++i) {
			this.add_jump(i + 1);								// index 0 is not used, so increase by one
			
			// set z-index;
			photos[i].style.zIndex	= --zindex;
			
			// find the image element
			if (photos[i].tagName.toLowerCase() == 'img') {
				img	= photos[i];
			} else {
				img = photos[i].getElementsByTagName('img')[0];
			}
			
			this.add(img, i + 1);								// index 0 is not used, so increase by one
		}
		
		this.add_jump('next &gt;', 'next');
		
		return this;
	},
	
	
	
	add : function(img, index)
	{
		var obj	= this;
		
		// check if image has loaded
		if (!img.complete || (typeof img.naturalWidth != "undefined" && img.naturalWidth === 0)) {
			W.Event.add(img, 'load', function(e) { obj.init_photo(this, index); });
		} else {
			this.init_photo(img, index);
		}
	},
	
	
	
	init_photo : function(img, index)
	{
		var obj	= this;
		
		this.photos[index] = img;
		if (this.click_advance) { W.Event.add(img, 'click', function(e) { obj.jump(e, 'next'); }); }
		
		if (this.caption) {
			var p		= document.createElement('p');
			p.id		= 'caption_' + index;
			p.innerHTML	= img.title;
			
			this.find_container(index).appendChild(p);
		}
		
		this.activate_jump(index);
		
		if (index == 1) {
			this.fade_in();
			this.select();
		}
	},
	
	
	
	key_nav : function(e)
	{
		var code	= e.charCode || e.keyCode;
		
		if (!this.swap || 'photo_' + this.swap.current.id == this.class_name) {
			if (code == 39) {
				this.next();
				this.auto	= false;
			} else if (code == 37) {
				this.previous();
				this.auto	= false;
			}
		}
	},
	
	
	
	add_jump : function(index, class_name)
	{
		var li = document.createElement('li');
		
		var a	= document.createElement('a');
		if (class_name) { a.className = class_name; }
		a.onclick	= this.jump.bind(this, index);
		//a.href		= '#';
		a.innerHTML	= '<span>' + index + '</span>';
		
		li.appendChild(a);
		if (this.nav) { this.nav.appendChild(li); }
	},
	
	
	
	jump : function(e, index)
	{
		W.Event.stop(e);

		//if (index == 'next') return this.next();
		//if (index == 'previous') return this.previous();
		
		//if (!this.photos[index]) return false;
		
		if (index == this.index) { return; }
		
		for (var tween in this.tween) {
			this.tween[tween].stop();
		}
		
		//this.set_opacity_in(100);
		if (this.index != this.prev_index) { this.set_opacity_out(0); }
		
		clearTimeout(this.timer);
		
		this.fade_out();
		
		//this.index	= index;
		if (index == 'next') {
			this.next();
		} else if (index == 'previous') {
			this.previous();
		} else {
			this.index = index;
			if (this.crossfade) { this.fade_in(); }
		}
		
		this.select();
		this.activate_previous_next();
		this.auto	= false;
	},
	
	
	
	activate_jump : function(index)
	{
		if (!this.nav) { return; }
		
		var lis = this.nav.getElementsByTagName('li');
		var li	= lis[index];
		if (li) { W.Dom.addClassName(li, 'ready'); }
		
		if (this.photos.length == (lis.length - 1)) { 
			this.activate_next(true); 							// activate next button once all photos are loaded
			if (this.loop) { this.activate_previous(true); }	// activate previous button if looping is allowed
		}
	},
	
	
	
	activate_previous : function(state)
	{
		if (!this.nav) { return; }
		
		var li	= this.nav.getElementsByTagName('li')[0];
		if (li) {
			state? W.Dom.addClassName(li, 'ready') : W.Dom.removeClassName(li, 'ready');
		}
	},
	
	
	
	activate_next : function(state)
	{
		if (!this.nav) { return; }
		
		var lis = this.nav.getElementsByTagName('li');
		var li	= lis[lis.length - 1];
		if (li) { 
			state? W.Dom.addClassName(li, 'ready') : W.Dom.removeClassName(li, 'ready');
		}
	},
	
	
	
	activate_previous_next : function()
	{
		if (this.loop || this.index > 1) { this.activate_previous(true); } else { this.activate_previous(false); }
		if (this.loop || this.index < (this.photos.length - 1)) { this.activate_next(true); } else { this.activate_next(false); }
	},
	
	
	
	select : function()
	{
		if (!this.nav) { return; }
		
		var lis		= this.nav.getElementsByTagName('li');
		var index	= this.index;
		
		for (var i = 0, max = lis.length; i < max; ++i ) {
			if (i == index) { W.Dom.addClassName(lis[i], 'selected'); } else { W.Dom.removeClassName(lis[i], 'selected'); }
		}
		
		W.Event.broadcast('onPhotoSelect', {source: this, index: index});
	},
	
	
	
	fade_in : function()
	{
		var start	= 0;
		var change	= 100;
		
		delete this.tween.fade_out;

		this.tween.fade_in	= new W.Tween({start: start, change: change, duration: this.duration, obj: this, bind: 'set_opacity_in', method: 'linear', callback: 'finish'});
	},
	
	
	
	fade_out : function()
	{
		var start 			= 100;
		var change			= -100;
		this.prev_index	= this.index;
		
		delete this.tween.fade_in;
		
		var cb	= 'fade_in';
		if (this.crossfade) { cb = false; }
		this.tween.fade_out	= new W.Tween({start: start, change: change, duration: this.duration, obj: this, bind: 'set_opacity_out', method: 'linear', callback: cb});
	},
	
	
	
	set_opacity_in : function(num)
	{
		var div = this.find_container(this.index);
		//console.log(div.innerHTML);
		div.style.display	= 'block';
		
		this.set_opacity(div, num);
	},
	
	
	
	set_opacity_out : function(num)
	{
		var div	= this.find_container(this.prev_index);
		
		this.set_opacity(div, num);
	},
	
	
	
	find_container : function(index)
	{
		var elem	= this.photos[index];
		
		while (!W.Dom.hasClassName(elem, this.class_name) && elem.tagName.toLowerCase() != 'body') {
			elem	= elem.parentNode;
		}
		
		return elem;
	},
	
	
	
	set_opacity : function(elem, num)
	{
		elem.style.opacity	= num / 100;
		elem.style.filter	= 'alpha(opacity=' + num + ')';
		if (num <= 0) { elem.style.display = 'none'; }
	},
	
	
	
	next : function()
	{
		if (this.photos.length == 2) { return; }	// bail out if there's only 1 photo (0 is empty, 1 is the first photo, so length of 2 = 1 photo
		
		if (this.index < (this.photos.length - 1) || this.loop) { this.fade_out(); }
		
		++this.index;
		if (this.index == this.photos.length) {
			if (!this.loop) {
				this.prev_index	= this.index - 1;
				this.index = 1;
				return;
			}
			this.index = 1;
		}
		
		if (this.crossfade) { this.fade_in(); }
		this.select();
		this.activate_previous_next();
	},
	
	
	
	previous : function()
	{
		this.fade_out();
		
		--this.index;
		if (this.index === 0) { this.index = this.photos.length - 1; }
		
		if (this.crossfade) { this.fade_in(); }
		this.select();
		this.activate_previous_next();
	},
	
	
	
	pause : function()
	{
		for (var tween in this.tween) {
			this.tween[tween].pause();
		}
		
		clearTimeout(this.timer);
	},
	
	
	
	resume : function()
	{
		var has_tweens	= false;
		
		for (var tween in this.tween) {
			has_tweens	= true;
			this.tween[tween].resume();
		}
		
		if (!has_tweens) {
			this.finish();
		}
	},
	
	
	
	stop : function()
	{
		/* same as pause except fade in photo is set to 100 opacity, and fade out photo is set to 0 */
		for (var tween in this.tween) {
			this.tween[tween].stop();
			if (tween == 'fade_out') { 
				this.set_opacity_out(0);
			} else if (tween == 'fade_in') {
				this.set_opacity_in(100);
			}
		}
		
		clearTimeout(this.timer);
	},
	
	
	
	finish : function()
	{
		var obj		= this;
		
		delete this.tween.fade_in;

		if (this.auto) {
			if (!this.swap || 'photo_' + this.swap.current.id == this.class_name) {
				this.timer	= setTimeout(function() { obj.next(); }, this._pause);
			}
		}
	},
	
	
	
	onSwapSelectStart : function(e)
	{
		this.pause();
	},
	
	
	
	onSwapSelectStop : function(e)
	{
		if ('photo_' + e.id == this.class_name) {
			//this.auto	= true;
			this.resume();
			//if (this.tween.fade_in || this.tween.fade_out) { this.resume(); } else { this.finish(); }
		}
	}
	
};
