var CM = { };

/*-------------------------------- Gallery --------------------------------*/

CM.Gallery = Class.create({
	initialize: function(itemInfos, showThumbnails) {	
		this.element = $('flipbook');
		
		this.unit = -1; // Not yet loaded
		
		this.items = [];
		
		var base = this;
		
		var i = 0;
		
		itemInfos.each(function(info) {
			var item = new GalleryItem(i, info);
			
			base.items.push(item);
			
			i++;
		});
		
		this.captionEl = $('caption');
		
		this.prevLink = this.element.down('.previousLink');
		this.nextLink = this.element.down('.nextLink');
		
		this.prevLink.on('click', this.viewPrevious.bind(this));
		this.nextLink.on('click', this.viewNext.bind(this));
		
		if(this.items.length == 1) {
			this.prevLink.hide();
			this.nextLink.hide();
		}
		else {
			blockSelection(this.prevLink);
			blockSelection(this.nextLink);
		}
		
		this.canvasEl = this.element.down('.canvas');
		this.artwork = this.element.down('.artwork');
		
		this.animating = false;
		
		if(showThumbnails) {
			this.thumbStrip = new CM.Thumbnails(/*element*/ 'imageThumbnails', /*stage*/ base);
		}
		
		var hash = window.location.hash;
		
		if(hash && hash.length > 1) {
			var hashValue = hash.split("#")[1];
			
			var itemIndex = parseInt(hashValue, 10) - 1;
				
			this.view(itemIndex);
		}
		else {
			this.view(0);
		}
				
		new HashMonitor({ 
			onChange: this.onHashChange.bind(this)
		});
		
		document.on('keydown', this.onKeyDown.bind(this));
	},
	onKeyDown: function(e) {
		return;
		
		switch(e.keyCode) {
			case 37: this.viewPrevious(); 	break;
			case 39: this.viewNext();  		break;
		}
	},
	onHashChange: function(hash) {	
		if(hash && hash.length > 1) {
			
			var hashValue = hash.split('#')[1];
			
			var itemIndex = parseInt(hashValue, 10) - 1;
					
			if(itemIndex != this.unit) {			
						
				this.view(itemIndex);	
			}
		}
	},
	view: function(itemIndex) {
		if(this.items.length != 0 && ((itemIndex + 1) > this.items.length)) {
		
			// LOOP
			this.view(0);
			
			return;
		}
		
		var base = this;
		
		if(itemIndex == this.unit) {		
			return; // don't load again.
		}		
				
		var item = this.items[itemIndex];
				
		if(!item) {			
			return;
		}
		
		this.unit = itemIndex;
		
		window.location = "#" + item.number;
		
		var previousItem = this.items[itemIndex - 1];
		var nextItem = this.items[itemIndex + 1];
		
		if(previousItem) {
			previousItem.load();
		}
		
		if(nextItem) {
			nextItem.load();
		}
		
		if(itemIndex == 0) {
			this.prevLink.addClassName('disabled');
		}
		else {
			this.prevLink.removeClassName('disabled');
		}
		
		if((itemIndex + 1) == this.items.length) {
			this.nextLink.addClassName('end');
		}
		else {
			this.nextLink.removeClassName('end');
		}
		
		this.animate();
	},
	viewNext: function() {
		this.view(this.unit + 1);
	},
	viewPrevious: function() {
		this.view(this.unit - 1);
	},
	animate: function() {	
		var item = this.items[this.unit];
		
		var base = this;
		
		// Hide the caption
		this.captionEl.hide();
					
		// Hide the artwork		
		this.artwork.setOpacity(0);
		
		if(!item.media.isLoaded) {
			this.canvasEl.addClassName('loading');
		}
		
		// Fade the image in once it loads
		item.load(this.onLoad.bind(this));
				
		// Set the caption
		if(item.description.length > 0) {
			this.captionEl.update(item.description);
			
			this.captionEl.show(); 
		}
		
		// Do the thumbnail stuff
		if(this.thumbStrip) {			
			this.thumbStrip.selectThumbnail(this.unit);
		}
	},
	onLoad: function(media) {
		var item = this.items[this.unit];
							
		var base = this;
			
		var newArtworkEl = new Element('div', {
			'class': 'artwork'
		});
		
		newArtworkEl.style.backgroundImage = 'url("' + media.src + '")';
		newArtworkEl.setOpacity(0);
		
		base.artwork.purge();
		
		base.artwork.replace(newArtworkEl);
		
		base.artwork = newArtworkEl;
		
		var appearEffect = new S2.FX.Morph(base.artwork, { 
			style: 'opacity:1',
			delay: 0,
			duration: 0.5,
			accelerate: true,
			before: function() {
				
			},
			after: function() { 
				base.canvasEl.removeClassName('loading');
			}
		});
		
		appearEffect.play();
	}
});

var GalleryItem = Class.create({
	initialize: function(index, info) {
		this.description = info.description;
		
		this.media = info.media;
		
		this.image = new Image();
		
		this.index = index;
		this.number = index + 1;
		this.isLoading = false;

		this.media.isLoaded = false;
		
		var rendition = this.media.renditions[0];
		
		this.media.width = rendition.width;
		this.media.height = rendition.height;
		this.media.url = rendition.url;
		
		this.errorCount = 0;
	},
	load: function(callback) {
		var base = this;
		
		if(this.media.isLoaded) {
		
			if(callback) {
				callback(this.image);
			}
			
			return;
		}
		
		if(this.isLoading) {
			
			if(callback) {
				callback(base.image);
			}
			return;
		}
		
		this.isLoading = true;		
				
		this.image.onload = function() {
			base.media.isLoaded = true;
			
			if(callback) {
				callback(base.image);
			}
		};
				
		this.image.onerror = function() {
			base.errorCount++;
			base.isLoading = false;
			
			if(base.errorCount < 3) { 
				base.load(callback);
			}		
		};


		this.image.src = this.media.url;
	}
});

/*-------------------------------- Video Stage --------------------------------*/

CM.VideoStage = Class.create({
	initialize: function(itemInfos, showThumbnails) {		

		this.items = itemInfos;
		
		this.unit = -1;
				
		if(showThumbnails) {
			this.thumbStrip = new CM.Thumbnails('videoThumbnails', this);
		}
		
		this.element = $('videoContainer');
		
		this.captionWrapper = this.element.down('.caption');
		
		var hash = window.location.hash;
		
		if(hash && hash.length > 1) {
			var hashValue = hash.split("#")[1];
			
			var itemIndex = parseInt(hashValue, 10) - 1;
						
			this.view(itemIndex);
		}
				
		new HashMonitor({ 
			onChange: this.onHashChange.bind(this)
		});
	},

	onHashChange: function(hash) {	
		if(hash && hash.length > 1) {
			
			var hashValue = hash.split('#')[1];
			
			var itemIndex = parseInt(hashValue, 10) - 1;
					
			if(itemIndex != this.unit) {			
						
				this.view(itemIndex);	
			}
		}
	},
	view: function(index) {	
		var item = this.items[index];
		
		if(index == this.unit) {					
			return; // don't load again.
		}
		
		if(item) {
			this.unit = index;
			
			window.location = "#" + (index + 1);
				
			this.internalView(item);
		}		
	},
	
	internalView: function(item) {
		
		if(!item || !item.media) {
			return;
		}
		
		var renditions = item.media.renditions;
		
		var sources = [];
		
		
		renditions.each(function(r) {						
			sources.push(new MediaSource(r.url, r.type));
		});
		
		var caption = item.description;
		var poster = item.media.poster.renditions[0];
	
		var captionEl = this.element.down('.caption');
		var captionText = captionEl.down();
		
		if(caption) {			
			captionText.update(caption);
			
			this.element.removeClassName('noCaption');
		}
		else {
			this.element.addClassName('noCaption');
		}
								
		player.setPosterSrc(poster.url);
		
		player.setSources(sources);
		
		player.reload();
		
		if(this.thumbStrip) {			
			this.thumbStrip.selectThumbnail(this.unit);
		}
	}
});

/*-------------------------------- Thumbnails --------------------------------*/

CM.Thumbnail = Class.create({
	initialize: function(index, element, strip) {
		this.element = element;
		this.index = index;
		
		this.strip = strip;
		this.stage = strip.stage;
		
		this.imageEl = element.down('img');
		
		this.width = this.imageEl.getWidth();
		
		this.element.observe('click', this.select.bind(this));
	},
	select: function() {
		this.strip.element.select('.selected').each(function(el) {
			el.removeClassName('selected');
		});
		
		this.element.addClassName('selected');
		
		if(this.stage) {
			if(this.stage.unit != this.index) {
				this.stage.view(this.index);
			}
		}
	},
	load: function() {
		if(this.imageEl.src.endsWith("c.gif")) {
			this.imageEl.src = this.imageEl.getAttribute('data-src');
		}
	}
});

CM.Thumbnails = Class.create({
	initialize: function(element, stage) {
		var base = this;
		
		this.element = $(element);
		
		this.stage = stage;
		
		this.thumbnails = [];
		
		var i = 0;
		
		this.setCount = 0;
		this.currentSet = 0;
		
		this.setEls = this.element.select('.set');
		
		var setWidth = this.element.getWidth();		
		
		this.setEls.each(function(setEl) {
			base.setCount++;
			
			var widthAccumulator = 0;
			
			setEl.select('li').each(function(liEl) {
				var thumbnail = new CM.Thumbnail(i, liEl, base);
				
				widthAccumulator += liEl.getWidth() + 10; // .width;
								
				thumbnail.setNumber = base.setCount;
				
				base.thumbnails.push(thumbnail);
				
				i++;
			});

			setEl.down('ul').style.width = widthAccumulator + 'px';			
		});
				
		this.viewportEl = this.element.down('.viewport');
		this.prevEl = this.element.down('.previous');
		this.nextEl = this.element.down('.next');
		
		this.prevEl.on('click', this.loadPreviousSet.bind(this));
		this.nextEl.on('click', this.loadNextSet.bind(this));
		
		if(this.setCount == 1) {
			this.prevEl.hide();
			this.nextEl.hide();
		}
	},
	selectThumbnail: function(itemIndex) {		
		var thumbnail = this.thumbnails[itemIndex];
		
		if(thumbnail) {
			thumbnail.select();
			
			this.loadSet(thumbnail.setNumber);
		}
	},
	loadPreviousSet: function() {
		this.loadSet(this.currentSet - 1);
	},
	loadNextSet: function() {	
		this.loadSet(this.currentSet + 1);
	},
	loadSet: function(setNumber) {
		if(!this.hasSet(setNumber) || this.currentSet == setNumber) {
			return;
		}
		
		this.currentSet = setNumber;
		
		if(setNumber == 1) {
			this.prevEl.addClassName('disabled');
		}
		else {
			this.prevEl.removeClassName('disabled');
		}
		
		if(this.hasSet(setNumber + 1)) {
			this.nextEl.removeClassName('disabled');
		}
		else {
			this.nextEl.addClassName('disabled');
		}

		var setEl = this.setEls[setNumber - 1];
		
		if(setEl) {			
			setEl.select('img.lazy').each(function(imgEl) {					
				imgEl.removeClassName('lazy');
					
				imgEl.src = imgEl.readAttribute('data-src');
			});
		
			this.moveTo(setEl, this.viewportEl, { duration: 0.5 }  );	
		}		
	},
	hasSet: function(setNumber) {	
		return setNumber <= this.setCount && setNumber > 0;
	},
	moveTo: function(element, container, options) {    	
	    var containerOffset = container.cumulativeOffset();
	    var elementOffset = element.cumulativeOffset();
		
		var x = (elementOffset[0]-containerOffset[0]);
		var y = (elementOffset[1]-containerOffset[1]);
		
		var scroll = new S2.FX.SmoothScroll(container, { 
			to: x,
			duration: 0.5,
			after: function() { 
				// log.info('completed scroll'); 
			}
		});

		scroll.play();
	}
});


function blockSelection(el) {
	el.focus();
	el.onselectstart = function () { return false; };
};
	
function unblockSelection(el) {
	el.onselectstart = function () { return true; };
}


/*-------------------------------- Hash Monitor --------------------------------*/
var HashMonitor = Class.create({
	initialize: function(options) {		
		if ('onhashchange' in window) {   		
    		window.onhashchange = function() {
    			var hash = window.location.hash;
    			    						
				options.onChange(window.location.hash);
    		};
		}
		else {
			var base = this;
			
			this.lastHash = window.location.hash;
			
			// Monitor the forward and back events
			new PeriodicalExecuter(function(pe) {
				var hash = window.location.hash;
				
	  			if(hash == base.lastHash) {
					return;
				}
				
				// The hash has changed
				base.lastHash = hash;
								
				options.onChange(hash);
			}, 0.2);
		}
	}
});

S2.FX.Operators.SmoothScroll = Class.create(S2.FX.Operators.Base, {
  initialize: function($super, effect, object, options) {  
  
  	options.transition = S2.FX.Transitions.webkitCubic; //sinusoidal;
  		
    $super(effect, object, options);
    
    this.start = object.scrollLeft;
    this.end = this.options.scrollTo;
  },

  valueAt: function(position) {
    return this.start + ((this.end - this.start) * position);
  },

  applyValue: function(value){
    this.object.scrollLeft = value.round();
  }
});

S2.FX.SmoothScroll = Class.create(S2.FX.Element, {
  setup: function() {
    	
    this.animate('smoothScroll', this.element, { 
    	mode: 'absolute',
    	scrollTo: this.options.to
    });
  }
});
