﻿
var Calliope = new Class({
	Implements: [Options],
	initialize: function(cOptions){
		this.setOptions(cOptions);
		
		// objects
		this.overlay = null;
		this.overlayFx = null;
		this.modalFloat = null;
		this.modalFloatOnFx = null;
		this.modalFloatOffFx = null;
		this.modalFloatTransFx = null;
		this.videoWrap = null;
		this.imageFx = null;
		this.buttonClose = null;
		this.buttonCloseFx = null;
		this.buttonNext = null;
		this.buttonPrevious = null;
		this.stripe = null;
		this.stripeFx = null;
		this.stripeTitle = null;
		this.currentRef = null;
		this.currentImagePath = null;
		this.currentImageID = 0;
		this.nextImageID = 0;
		this.previousImageID = 0;
		this.isFirst = true;
		this.isVideo = false;
		
		this.image = new Asset.images($$(this.options.selector).getProperty('large-image'), {
			onProgress: function(){
			},
			onComplete: function(){
			}
		});
		
		this.url = $$(this.options.selector).getProperty('image-url');
		this.title = $$(this.options.selector).getProperty('image-title');
		
		var me = this;
		$$(this.options.selector).addEvents({
			'click': function(){
				me.currentImagePath = this.getProperty('large-image');
				me.currentRef = this;
				if(this.getProperty('image-url')) me.isVideo = this.getProperty('image-url').indexOf('youtube') > -1 ? true : false;
				if(me.isVideo) me.videoUrl = this.getProperty('image-url').replace('watch?v=', 'v/');
				me.renderModal();
			}
		});
	},
	
	options: {
		selector: 'IMG',
		showStripe: true,
		stripeHeight: 100,
		stripeColor: '#FFF',
		stripeBackgroundColor: '#000',
		stripeOpacity: 0.8,
		overlayOpacity: 0.5,
		videoWidth: 640,
		videoHeight: 505,
		transitionImage: 'linear',
		transitionImageDuration: 500,
		transitionFrameBlink: 'back:out',
		transitionFrameBlinkDuration: 600,
		transitionFrameTrans: 'expo:out',
		transitionFrameTransDuration: 300,
		transitionStripe: 'back:out',
		transitionStripeDuration: 300
	},
	
	renderModal: function(){

		this.overlay = new Element('div').setStyles({
			position: 'absolute',
			top: '0',
			left: '0',
			width: document.body.offsetWidth - (window.ie ? 24 : 0),
			height: document.body.offsetHeight - (window.ie ? 4 : 0),
			backgroundColor: '#000',
			opacity: '0',
			zIndex: '20'
		}).addEvent('click', this.destroyModal.bind(this)).inject(document.body, 'top');
		
		this.modalFloat = new Element('div').addClass('calliopeWrap').setStyles({
			opacity: '0',
			zIndex: '21'
		}).inject(document.body, 'bottom');
		
		this.overlayFx = new Fx.Morph(this.overlay, {
			duration: this.options.transitionFrameTransDuration, 
			transition: this.options.transitionFrameTrans, 
			wait: true
		});
		
		this.modalFloatOnFx = new Fx.Morph(this.modalFloat, {
			duration:this.options.transitionFrameBlinkDuration, 
			transition: this.options.transitionFrameBlink,
			wait: true
		});
		this.modalFloatOffFx = new Fx.Morph(this.modalFloat, {
			duration: this.options.transitionFrameTransDuration, 
			transition: this.options.transitionFrameTrans,
			wait: true
		});
		this.modalFloatTransFx = new Fx.Morph(this.modalFloat, {
			duration: this.options.transitionFrameTransDuration, 
			transition: this.options.transitionFrameTrans,
			wait: true
		});
		
		this.buttonClose = new Element('div').addClass('close').setStyles({
			opacity: 0,
			top: 0,
			zIndex: '30'
		}).addEvents({'click': function(){
			this.destroyModal();
		}.bind(this)}).inject(this.modalFloat, 'top');
		
		if(this.options.showStripe){
			this.stripe = new Element('div').setStyles({
				position: 'absolute',
				opacity: 0,
				border: 'none',
				height: this.options.stripeHeight - 10,
				left: '3px',
				color: this.options.stripeColor,
				background: this.options.stripeBackgroundColor,
				zIndex: '30'
			}).inject(this.modalFloat);
			
			this.stripeFx = new Fx.Morph(this.stripe, {
				duration: this.options.transitionFrameTransDuration, 
				transition: this.options.transitionFrameTrans,
				wait: true
			});
			
			this.buttonNext = new Element('div').addClass('left').setStyles({
				opacity: 0,
				height: this.options.stripeHeight - 12,
				zIndex: '31'
			}).addEvents({'click': function(oEvent){
				oEvent.stop();
				this.next();
			}.bind(this)}).inject(this.modalFloat);
			
			this.buttonPrevious = new Element('div').addClass('right').setStyles({
				opacity: 0,
				height: this.options.stripeHeight - 12,
				zIndex: '31'
			}).addEvents({'click': function(oEvent){
				oEvent.stop();
				this.previous();
			}.bind(this)}).inject(this.modalFloat);
			
			this.stripeTitle = new Element('div').addClass('title').setStyles({
				opacity: 0,
				height: this.options.stripeHeight - 24,
				zIndex: '31'
			}).inject(this.modalFloat);
		}
		
		this.overlayFx.start({'opacity': [0, this.options.overlayOpacity]}).chain(function(){
			if(this.isVideo){
				this.options.showStripe = false;
				this.renderVideo();
			}else{
				for(var nIndex = 0; nIndex < this.image.length; nIndex++){
					if(this.image[nIndex].src.contains(this.currentImagePath)) this.currentImageID = nIndex;
				}
				this.renderImage(this.currentImageID);
			}
		}.bind(this));

	},
	
	renderVideo: function(){
		this.modalFloat.setStyles({
			width: this.options.videoWidth,
			height: this.options.videoHeight + 25
		});
		this.videoWrap = new Element('div').setProperty('id', 'calliopeFrame0').setStyles({
			position: 'absolute', 
			opacity: 0, 
			width: this.options.videoWidth,
			height: this.options.videoHeight + 25,
			paddingTop: '30px',
			zIndex: '20'
		}).set('html', '<object width="' + this.options.videoWidth + '" height="' + this.options.videoHeight + '"><param name="movie" value="' + this.videoUrl + '&autoplay=1&hl=en&fs=1&"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="' + this.videoUrl + '&autoplay=1&hl=en&fs=1&" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="' + this.options.videoWidth + '" height="' + this.options.videoHeight + '"></embed></object>').inject(this.modalFloat);
		
		this.modalFloat.position();
		
		this.modalFloatOnFx.start({
			opacity: [0, 1],
			top: [this.currentRef.getPosition().y, this.videoWrap.getPosition().y],
			left: [this.currentRef.getPosition().x, this.videoWrap.getPosition().x],
			width: [this.currentRef.getSize().x, this.videoWrap.getSize().x],
			height: [this.currentRef.getSize().y, this.videoWrap.getSize().y]
		}).chain(function(){
			this.videoWrap.setStyle('opacity', 1);
				this.renderCommandLayer();
		}.bind(this));
	},
	
	renderImage: function(nImageID){
		
		this.injectImage(nImageID);

		var oImage = new Element('div').setProperty('id', 'calliopeFrame' + nImageID).addClass('image').setStyles({
			opacity: 0, 
			background: 'url(' + this.image[nImageID].src + ')',
			width: this.image[nImageID].getSize().x,
			height: this.image[nImageID].getSize().y,
			zIndex: '20'
		}).inject(this.modalFloat);

		this.imageFx = new Fx.Morph(oImage, {
			duration: this.options.transitionImageDuration, 
			transition: this.options.transitionImage,
			wait: true
		});
		
		if(this.isFirst){
			this.modalFloatOnFx.start({
				opacity: [0, 1],
				top: [this.currentRef.getPosition().y, this.image[nImageID].position({returnPos: true}).top],
				left: [this.currentRef.getPosition().x, this.image[nImageID].position({returnPos: true}).left],
				width: [this.currentRef.getSize().x, this.image[nImageID].getSize().x],
				height: [this.currentRef.getSize().y, this.image[nImageID].getSize().y]
			}).chain(function(){
				this.imageFx.start({opacity: [0, 1]}).chain(function(){
					this.renderCommandLayer();
				}.bind(this));
			}.bind(this));
		}else{
			var oPrevImage = $('calliopeFrame' + this.currentImageID);
			var oPrevImageFx = new Fx.Morph(oPrevImage, {
				duration: this.options.transitionImageDuration, 
				transition: this.options.transitionImage,
				wait: true
			});
			this.hideCommandLayer();
			oPrevImageFx.start({opacity: [1, 0]}).chain(function(){

				this.modalFloatTransFx.start({
					top: [this.image[this.currentImageID].position({returnPos: true}).top, this.image[nImageID].position({returnPos: true}).top],
					left: [this.image[this.currentImageID].position({returnPos: true}).left, this.image[nImageID].position({returnPos: true}).left],
					width: [this.image[this.currentImageID].getSize().x, this.image[nImageID].getSize().x],
					height: [this.image[this.currentImageID].getSize().y, this.image[nImageID].getSize().y]
				}).chain(function(){;			
					this.imageFx.start({opacity: [0, 1]}).chain(function(){
						this.renderCommandLayer();
					}.bind(this));
					if($('calliopeFrame' + this.currentImageID)) $('calliopeFrame' + this.currentImageID).destroy();
					if($('calliopeTemp' + this.currentImageID)) $('calliopeTemp' + this.currentImageID).destroy();
					this.currentImageID = nImageID;
				}.bind(this));
			}.bind(this));
		}
	},
	
	injectImage: function(nImageID){
		this.image[nImageID].setStyles({
			position: 'absolute',
			top: '0px',
			left: '0px',
			zIndex: '20',
			visibility: 'hidden'
		}).setProperty('id', 'calliopeTemp' + nImageID).inject(document.body, 'bottom');
	},
	
	renderCommandLayer: function(){
		this.buttonClose.setStyles({
			opacity: 0,
			left: this.modalFloat.getSize().x - this.buttonClose.getSize().x - 10,
			top: '0px'
		});
		
		this.buttonCloseFx = new Fx.Morph(this.buttonClose, {
			duration: this.options.transitionFrameTransDuration, 
			transition: this.options.transitionFrameTrans,
			wait: true
		});
		
		this.buttonCloseFx.start({
			opacity: [0, 1],
			top: [-5, 0]
		});
		
		if(this.options.showStripe) this.renderStripe();
	
	},
	
	hideCommandLayer: function(){
		this.buttonCloseFx.start({
			opacity: [1, 0],
			top: [0, -5]
		});
		if(this.options.showStripe) this.hideStripe();
	},
	
	renderStripe: function(){
		
		this.stripe.setStyles({
			opacity: 0,
			top: this.modalFloat.getSize().y - this.options.stripeHeight - 10,
			width: this.modalFloat.getSize().x - 15
		});
		
		this.stripeFx.start({
			opacity: [0, this.options.stripeOpacity],
			top: [this.modalFloat.getSize().y - this.options.stripeHeight + 3, this.modalFloat.getSize().y - this.options.stripeHeight - 3]
		}).chain(function(){
			if(this.image.length - 1 > this.currentImageID){
				this.buttonNext.setStyles({
					opacity: 1,
					top: this.modalFloat.getSize().y - this.options.stripeHeight - 2
				});
			}
			if(this.currentImageID != 0){
				this.buttonPrevious.setStyles({
					opacity: 1,
					top: this.modalFloat.getSize().y - this.options.stripeHeight - 2
				});
			}
			this.stripeTitle.setStyles({
				opacity: 1,
				width: this.modalFloat.getSize().x - 100,
				top: this.modalFloat.getSize().y - this.options.stripeHeight - 2
			}).set('html', this.title[this.currentImageID] ? this.title[this.currentImageID].replace('&', '&amp;') : '');
		}.bind(this));
	},
	
	hideStripe: function(){
		this.buttonNext.setStyles({opacity: 0});
		this.buttonPrevious.setStyles({opacity: 0});
		this.stripeTitle.setStyles({opacity: 0});
		this.stripeFx.start({
			opacity: [this.options.stripeOpacity, 0],
			top: [this.modalFloat.getSize().y - this.options.stripeHeight - 3, this.modalFloat.getSize().y - this.options.stripeHeight + 3]
		});
	},
	
	next: function(){
		var nTemp = this.currentImageID + 1 < this.image.length ? this.currentImageID + 1 : this.image.length - 1;
		this.isFirst = false;
		this.renderImage(nTemp);
	},
	
	previous: function(){
		var nTemp = this.currentImageID - 1 >= 0 ? this.currentImageID - 1 : 0;
		this.isFirst = false;
		this.renderImage(nTemp);
	},
	
	destroyModal: function(){
		this.isFirst = true;
		if(this.isVideo) this.videoWrap.destroy();
		this.modalFloatOffFx.start({'opacity': [1, 0]}).chain(function(){
			this.overlayFx.start({'opacity': [this.options.overlayOpacity, 0]}).chain(function(){
				this.modalFloat.destroy();
				this.overlay.destroy();
				if($('calliopeTemp' + this.currentImageID)) $('calliopeTemp' + this.currentImageID).destroy();
			}.bind(this));
		}.bind(this));
	}

});
