/*
Simple Gallery Script
Created by Rygor Kharytanovich 2009, rygorka@gmail.com
version: 0.1
*/

YAHOO.namespace('alekseynaumchik.app');

(function () {
	
	var Dom = YAHOO.util.Dom,
		Event = YAHOO.util.Event,
		CustomEvent = YAHOO.util.CustomEvent,
		Anim = YAHOO.util.Anim;
	
	var rand = function () {return ('' + Math.random()).substr(2)};
	
	Gallery = function(config) {
		this.init(config);
	}
	
	Gallery.CLASSES = {
		THUMB_ELEMENT: "links",
		THUMB_INFO: "info",
		THUMB_SELECTED: "active",
		PHOTO_ELEMENT: "photo",
		CONTROLS: "ctrls",
		CONTROLS_LEFT: "left",
		CONTROLS_RIGHT: "right"
	}
	
	Gallery.prototype = {
		updateDescr: function (idx) {
			var data = this.data[idx];
			this.descrHdrEl.innerHTML = "<span>" + data.sort + ".</span> " + data.title;
			this.descrTxtEl.innerHTML = data.description;
		},
		handleSelect: function (e, args) {
			this.updateDescr(args[0]);
		},
		init: function (config) {
			
			if (config.element !== undefined) this.element = config.element;
			if (config.data !== undefined) this.data = config.data;
			
			this.descrEl = Dom.getElementsByClassName('descr', 'div', this.element)[0];
			this.descrHdrEl = Dom.getElementsByClassName('hdr', 'p', this.descrEl)[0];
			this.descrTxtEl = Dom.getElementsByClassName('txt', 'p', this.descrEl)[0];
			
			this.thumbs = new YAHOO.alekseynaumchik.app.Gallery.Thumbs({
				element: Dom.getElementsByClassName(Gallery.CLASSES.THUMB_ELEMENT, 'div', this.element)[0]
			});
			
			this.photo = new YAHOO.alekseynaumchik.app.Gallery.Photo({
				element: Dom.getElementsByClassName(Gallery.CLASSES.PHOTO_ELEMENT, 'div', this.element)[0],
				data: this.thumbs.getData(),
				selected: this.thumbs.getSelected()
			});
			
			this.thumbs.selectEvent.subscribe(this.photo.handleSelect, this.photo, true);
			this.photo.selectEvent.subscribe(this.thumbs.handleSelect, this.thumbs, true);
			this.photo.selectEvent.subscribe(this.handleSelect, this, true);
			
		}
	}
	
	
	Gallery.Thumbs = function(config) {
		this.init(config);
	}
	
	Gallery.Thumbs.prototype = {
		
		getData: function () {
			return this.items;
		},
		
		getSelected: function () {
			return this.selected;
		},
		
		select: function (idx, silent) {
			
			var silent = silent || false;
			
			Dom.removeClass(this.items[this.selected], Gallery.CLASSES.THUMB_SELECTED);
			Dom.addClass(this.items[idx], Gallery.CLASSES.THUMB_SELECTED);
			
			this.selected = idx;
			
			if (!silent) {
				this.selectEvent.fire(idx);
			}
			
		},
		
		handleThumbClick: function (e, args) {
			Event.stopEvent(e);
			
			var idx = args[0];
			
			this.select(idx);
		},
		
		handleSelect: function (e, args) {
			
			var idx = args[0]
			
			this.select(idx, true);
			
		},
		
		initItems: function () {
			
			var idx = 0,
				els = this.element.getElementsByTagName('li');
			
			Dom.batch(els, function (el) {
				if (!Dom.hasClass(el, Gallery.CLASSES.THUMB_INFO)) {
					
					this.items.push(el);
					
					var anchor = el.getElementsByTagName('a')[0];
					
					Event.on(anchor, 'click', this.handleThumbClick, [idx], this);
					
					if (Dom.hasClass(el, Gallery.CLASSES.THUMB_SELECTED)) {
						this.selected = idx;
					}
					
					idx++;
				}
			}, this, true);
			
		},
		
		init: function (config) {
			
			if (config.element !== undefined) this.element = config.element;
			
			this.selected = null;
			this.items = [];
			
			this.initItems();
			
			this.selectEvent = new CustomEvent('select');
			
		}
	}
	
	
	Gallery.Photo = function(config) {
		this.init(config);
	}
	
	Gallery.Photo.prototype = {
		
		motion: false,
		
		isMotion: function () {
			return this.motion;
		},
		
		select: function (idx) {
			
			var me = this;
			
			this.selected = idx;
			this.motion = true;
			
			var anim = new YAHOO.util.Anim(this.curImg, {opacity: {to: 0}}, 0.5);
			anim.onComplete.subscribe(function () {
				
				var newImage = new Image();
				
				Event.on(newImage, 'load', function () {
					
					var anim1 = new YAHOO.util.Anim(this.curImg, {opacity: {to: 1}}, 0.5);
					anim1.onComplete.subscribe(function () {
						me.motion = false;
					});
					anim1.animate();
					
					var anim2 = new YAHOO.util.Anim(me.preloader, {opacity: {to: 0}}, 0.15);
					anim2.onComplete.subscribe(function () {
						Dom.setStyle(me.preloader, 'opacity', 0);
					});
					anim2.animate();
					
					this.curImg.src = newImage.src;
					
				}, this, true);
				
				new YAHOO.util.Anim(this.preloader, {opacity: {to: 1}}, 0.15).animate();
				
				newImage.src = this.data[idx].getElementsByTagName('a')[0].href;
				
			}, this, true);
			anim.animate();
			
			this.selectEvent.fire(idx);
			
		},
		
		handleAreaPrevMouseOver: function (e, args) {
			
			var relatedTarget = Event.getRelatedTarget(e),
				el = args[0];
			
			if (!relatedTarget) {
				return;
			}
			
			do {
				
				if (relatedTarget == el) {
					return;
				}
				
				relatedTarget = relatedTarget.parentNode;
				
			} while (relatedTarget.tagName && relatedTarget.tagName.toLowerCase() != "html");
			
			Dom.setStyle(this.arrPrevEl, 'visibility', 'visible');
			var anim = new Anim(this.arrPrevEl, {opacity: {to: 0.7}}, 0.2).animate();
			
		},
		
		handleAreaPrevMouseOut: function (e, args) {
			
			var relatedTarget = Event.getRelatedTarget(e),
				el = args[0];
			
			if (!relatedTarget) {
				return;
			}
			
			do {
				
				if (relatedTarget == el) {
					return;
				}
				
				relatedTarget = relatedTarget.parentNode;
				
			} while (relatedTarget.tagName && relatedTarget.tagName.toLowerCase() != "html");
			
			var anim = new Anim(this.arrPrevEl, {opacity: {to: 0}}, 0.2);
			anim.onComplete.subscribe(function () {
				Dom.setStyle(this.arrPrevEl, 'visibility', 'visible');
			}, this);
			anim.animate();
			
		},
		
		handleAreaNextMouseOver: function (e, args) {
			
			var relatedTarget = Event.getRelatedTarget(e),
				el = args[0];
			
			if (!relatedTarget) {
				return;
			}
			
			do {
				
				if (relatedTarget == el) {
					return;
				}
				
				relatedTarget = relatedTarget.parentNode;
				
			} while (relatedTarget.tagName && relatedTarget.tagName.toLowerCase() != "html");
			
			Dom.setStyle(this.arrNextEl, 'visibility', 'visible');
			var anim = new Anim(this.arrNextEl, {opacity: {to: 0.7}}, 0.3).animate();
			
		},
		
		handleAreaNextMouseOut: function (e, args) {
			
			var relatedTarget = Event.getRelatedTarget(e),
				el = args[0];
			
			if (!relatedTarget) {
				return;
			}
			
			do {
				
				if (relatedTarget == el) {
					return;
				}
				
				relatedTarget = relatedTarget.parentNode;
				
			} while (relatedTarget.tagName && relatedTarget.tagName.toLowerCase() != "html");
			
			var anim = new Anim(this.arrNextEl, {opacity: {to: 0}}, 0.3);
			anim.onComplete.subscribe(function () {
				Dom.setStyle(this.arrNextEl, 'visibility', 'visible');
			}, this);
			anim.animate();
			
		},
		
		handleArrNextClick: function (e) {
			Event.stopEvent(e);
			
			if (this.isMotion()) {
				return false;
			}
			
			var idx = this.selected + 1;
			
			if (idx >= this.data.length) {
				idx = 0;
			}
			
			this.select(idx);
			
		},
		
		handleArrPrevClick: function (e) {
			Event.stopEvent(e);
			
			if (this.isMotion()) {
				return false;
			}
			
			var idx = this.selected - 1;
			
			if (idx < 0) {
				idx = this.data.length - 1;
			}
			
			this.select(idx);
			
		},
		
		handleSelect: function (e, args) {
			
			var idx = args[0]
			
			this.select(idx);
			
		},
		
		initControls: function () {
			
			var controlsEl = Dom.getElementsByClassName(Gallery.CLASSES.CONTROLS, 'ul', this.element)[0];
			this.areaPrevEl = Dom.getElementsByClassName(Gallery.CLASSES.CONTROLS_LEFT, 'li', controlsEl)[0];
			this.areaNextEl = Dom.getElementsByClassName(Gallery.CLASSES.CONTROLS_RIGHT, 'li', controlsEl)[0];
			this.arrPrevEl = this.areaPrevEl.getElementsByTagName('a')[0];
			this.arrNextEl = this.areaNextEl.getElementsByTagName('a')[0];
			
			Dom.setStyle(this.arrPrevEl, 'opacity', 0);
			Dom.setStyle(this.arrNextEl, 'opacity', 0);
			
			Event.on(this.areaPrevEl, 'mouseover', this.handleAreaPrevMouseOver, [this.areaPrevEl], this);
			Event.on(this.areaPrevEl, 'mouseout', this.handleAreaPrevMouseOut, [this.areaPrevEl], this);
			Event.on(this.areaNextEl, 'mouseover', this.handleAreaNextMouseOver, [this.areaNextEl], this);
			Event.on(this.areaNextEl, 'mouseout', this.handleAreaNextMouseOut, [this.areaNextEl], this);
			Event.on(this.arrNextEl, 'click', this.handleArrNextClick, this, true);
			Event.on(this.arrPrevEl, 'click', this.handleArrPrevClick, this, true);
			
		},
		
		initImages: function () {
			
			this.curImg = Dom.getElementsByClassName('image', 'img', this.element)[0];
			this.preloader = Dom.getElementsByClassName('preloader', 'img', this.element)[0];
			
		},
		
		init: function (config) {
			
			if (config.element !== undefined) this.element = config.element;
			if (config.data !== undefined) this.data = config.data;
			if (config.selected !== undefined) this.selected = config.selected;
			
			this.initControls();
			this.initImages();
			
			this.selectEvent = new CustomEvent('select');
			
		}
		
	}
	

	YAHOO.alekseynaumchik.app.Gallery = Gallery;
	
})();
