/*
v2.5 jgrauel 2010 5

Uses moo Framework inspired by milkBox class

 we plan for every call to the overlay- will have a set content wxh that matches the actual image loaded- or else the image will need to scale to fit
 combining the work done with the overlay in to a class that will incorporate html 5 and css3
 for video and transitions


*/


// the class
var LG_overlay = new Class({
	Implements:[Options,Events],
	
	options:{//set all the options here
		siteURL:'',
		baseURL: '',	// Prepend to external resource paths in case the images are not 
					// accessible via relative paths, for example, a remote host.  Must
					// include a trailing slash.
		overlayOpacity:0.4,
		overlayDuration:0.3,
		overlayColor:'#000000',
		topPlacement: '50%',// default for how far from browser top to it will be it a position is not passed
		leftPlacement: '50%',// default for how far from browser side to it will be it a position is not passed
		position: null,// object to set x,y of the holder
		initialWidth:null,// default width for holder  - will morph to fit content
		initialHeight:null,// default height for holder - will morph to fit content
		flashVersion:'9.25.0',// what flash plugin will be required
		contentColor:'#ffffff',// color of the ground below content
		contentBorderWidth:0,// how bid of border should be around the content
		contentBorderColor:'#000000',
		siteColor:'#444444',
		contentPadding:0,
		contentWidth:250,// default width for content if file dimension can't be determined
		contentHeight:250,// default height for content if file dimension can't be determined
		fixedSize: false,// does the image need to be scaled to fit in content
		addDropShadow: true,
		resizeMorph: true,// tween the morph from passed sizes to loaded sizes
		entryDuration:0.8,
		morphDuration:0.5,
		resizeTransition: 'sine:in:out',
		iframeScrollers: 'auto',// auto, yes, no
		iframePadW: 18,
		iframePadH: 0,
		showQTLogo: false,
		autoPlayMovie: true,
		movieControlType:'html5',//[qt,swf,html5]
		moviePad: 0,
		movieAutoPlay: true,
		sizeAdjustment: 20,
		movieControllerH: 0,// this should be dynamic to prevent issues, but for now should match height plus top margin and top padding
		showCustomController: true,	
		onClosed:$empty,
		onAssetReady:$empty,
		content:'',
		displayType:'asset' // 'asset', 'webpage', 'html'
	},

	maxWidth:null,
	movieW:null,
	fileType:'',
	
	// @param p {object}
    initialize: function(p){
    	//alert('NSOverlay: initialize');
    	this.setOptions(p);
    	//var self = this;
		this.content = this.options.content;// what will be displayed
		//var sExt = this.content.substr(this.content.lastIndexOf(".")+1,3).toLowerCase();
		this.options.displayType = this.options.displayType.toLowerCase();

		this.fileType = (this.options.displayType == 'asset')? this.getFileType(this.content) : '';// look 
		this.currentFile = null;// asset object to be created from file
		
		if(this.options.siteURL == '' || this.options.siteURL == 'undefined') this.options.siteURL = document.location;
		if(String(this.options.contentBorderWidth).indexOf('px') != -1) this.options.contentBorderWidth = Number(this.options.contentBorderWidth.substr(0,this.options.contentBorderWidth.indexOf('px')));
		this.isMoviePlaying = false;
			 		
		// add some extra padding for movies to account for controller and
		//this.fileType =='mov' || this.fileType =='m4v' || this.fileType =='mp4'|| this.fileType =='mpg' || this.fileType =='flv'

		if(this.options.displayType == 'video'){
			this.movieW = this.options.contentWidth;
			this.movieH = this.options.contentHeight;	
		};

		
		// add extra padding for iframes to accout for scrollbars appearing
		if(this.options.displayType == 'webpage'){
			
			this.iframeW = this.options.contentWidth;
			this.iframeH = this.options.contentHeight;
			
			
			this.options.contentWidth += (this.options.contentPadding*2);
			this.options.contentHeight += (this.options.iframePadH + (this.options.contentPadding*2));
			

			if(this.options.contentPadding > 0 ){
				this.options.contentWidth += this.options.iframePadW;
			};
			//console.log('[OVERLAY] frame w:'+this.iframeW+', h:'+this.iframeH);
		};

		// if didn't pass initial width, but did pass content size set to the same
		if(null == this.options.initialWidth || !this.options.resizeMorph) this.options.initialWidth = this.options.contentWidth;
		if(null == this.options.initialHeight || !this.options.resizeMorph) this.options.initialHeight = this.options.contentHeight;

		this.closed = true;
		this.first = true;
		
		this.setUpHTML();// prepare layout parts
		this.setSize();
		window.addEventListener("resize", this, false);

    	this.active = true;
    },
	
	getFileType: function(s){
		// will return the extension
		var ext = s.substr(s.lastIndexOf(".")+1,3).toLowerCase();
		if(s.indexOf('.swf') != -1 || s.indexOf('youtube.com') != -1 || s.indexOf('blip.tv') != -1 || s.indexOf('vimeo.com') != -1 || s.indexOf('pictage.com') != -1){
			ext = 'swf';// allows for swfs with external params
			this.options.displayType = 'flash';
		};
		
		switch(ext){
			case 'mov':
			case 'mp4':
			case 'm4v':
			case 'mpg':
			case 'flv':
				this.options.displayType = 'video';
			break;
		};
		
		return ext;
	},

	// functio to get the size of the window and store
	setSize: function(){
 		var w = window.innerWidth;//window.screen.availWidth
	    var h = window.innerHeight;//window.screen.availHeight
		//window.innerHeight
	    // set style on the images holder
	    //this.overlay.setStyles({ 'width':w, 'height': '100%'});//
	    //console.log("[OVERLAY] setSize(w:"+w+" h:"+h+")");
	    // make adjustments based on device, passed when init
	    // set initial sizes?
	    if(this.options.initialWidth > w) this.options.initialWidth = w;
	    if(this.options.initialHeight > h) this.options.initialHeight = h;
	    
    	// store for resizeing boundries
	    this.maxWidth = w - this.options.sizeAdjustment;
	    this.maxHeight = h - this.options.sizeAdjustment;//need to detect the type of menu bar 
	},
	
	// adjust the size of the conten
	// check if it is bigger
	_resize: function(el, w, h){
			var dim = el.getSize();
			if(null == h) h = dim.y;
			if(null == w) w = dim.x;

			// if the property is smaller than the 
			// corresponding gallery size then just keep it as is
			var newW = (w > this.maxWidth)? this.maxWidth : w;
			var newH = (h > this.maxHeight)? this.maxHeight : h;
			var per = 1;
			
			// detemine ration to use
	 		if(w > h){			 			
	 			var ratio = w/h;
	 			var tmpH = newW/ratio;
	 				newH = tmpH;	
	 		}else{
	 			var ratio = h/w;
	 			var tmpW = newH/ratio;
	 				newW = tmpW;//'auto' Math.round(imgW - (imgW*perc));
	 		};	
	 		
	 		// be sure we are smaller than max
	 		if(newH > this.maxHeight){
				per = this.maxHeight/newH;
				newH *= per;
				newW *= per;
			}else if(newW > this.maxWidth){
				per = this.maxWidth/newW;
				newH *= per;
				newW *= per;
			};
	 		
	 		newW = Math.round(newW);	
			newH = Math.round(newH);
			//console.log("[OVERLAY] setSize(neww:"+newW+" newh:"+newH+") - previous(w:"+w+" h:"+h+") this.currentFile.id="+this.currentFile.id);
			// if video may need to set wxh
			if(this.options.displayType == 'video' && el.get('tag') == 'video'){
				el.set({'height': newH, 'width': newW});//
			}else{
				el.setStyles({'height': newH, 'width': newW});//content
			};
			

	},
	
	_center: function(el, lft, tp){
			var size = el.getSize();
			if(null == tp) tp = -(size.y/2);// + (this.options.sizeAdjustment/2)+15)account for bar
			if(null == lft) lft = -(size.x/2);
			//'left':'50%', 'top': '50%',
			el.setStyles({marginLeft:lft+'px', marginTop:tp+'px' });
			//console.log("[OVERLAY]  _enter - margin left:"+lft+"|"+size.x+", margin top:"+tp+"|"+size.y);
	},

	/*---------------------------------------------
	* this method adds the struture to the dom, building each area to be used
	+ <body>
		<div id="nsOverlay" /> : tranparent covering 100% wxh
			
		<div id="nsHolder" : positioned in window - default centers
			<a id="nsClose /> :		
			<div id="nsLayout" > : styleable ground that is tweened in then loads content
				<div id="nsContent" > : display content here
					<div> : various content type div depending on file		
	
	---------------------------------------------*/
	setUpHTML:function(){
		// add to body tag
		var oBody = $(document.body);//$$('body')[0]
			
		if(this.options.overlayOpacity > 0){
			this.overlay = new Element('div', { 'id':'nsOverlay',
				//'styles':{'background-color':this.options.overlayColor}, 			
				'events':{
					'click' : this.closeOverlay.bind(this)
				}
				}).inject(oBody);//height:0px;opacity:0;,'styles':{'overflow':'hidden;'},
			//this.overlay.hide().observe('click', (function() { this.closeOverlay(); }).bind(this));
							
		};
		
		this.holder = new Element('div', {'id':'nsHolder'}).inject(oBody);//
		this.holder.setStyles({'width':this.options.initialWidth,'height':this.options.initialHeight});
		
		
		

				
		var clsWH = 21;//matches what is set in the css

		this.layout = new Element('div', {'id':'nsLayout'});
		this.layout.setStyles({'width': this.options.initialWidth, 'height': this.options.initialHeight, 'background-color':this.options.contentColor });
		
		// now we can do the shadow with CSS3 and not need all the extra divs
		this.layout.inject(this.holder);
		
		// add to holder div
		this.close = new Element('a',{'id':'nsClose',
			'events':{
				'click' : this.closeOverlay.bind(this)
			}
		}).inject(this.holder);
		
		// set positon of the holder
		if(this.options.position != null){
			var x = this.options.position.x;
			var y = this.options.position.y;
			// can use css3 to make the shadow so shoudl only need one div
			this.holder.setStyles({left: x+'px', top:y+'px'});			
			if(null != this.shadow) this.shadow .setStyles({left: 0 +'px' , top: 0+'px'});//		

		}else{
			// marginLeft: centers horizontally ,  marginTop centers vertically
			var mT = -(this.options.initialHeight/2);
			var mL = -(this.options.initialWidth/2);
			this._center(this.holder,mL,mT);
			//this.holder.setStyles({marginLeft:mL+'px', marginTop:mT+'px'});			
			//if(null != this.shadow) this.shadow .setStyles({marginLeft:mL+'px', marginTop:mT+'px'});// this keeps layout int the center

		};
			// build inside layout
			this.contentCnt = new Element('div', {'id':'nsContent'}).inject(this.layout);	//,'styles':{'visibility':'hidden'}	
			this.loader = new Element('div', {'id':'nsLoader'});// loader div to hold css animation
				
		
		//alert('NSOverlay: setUpHTML');				
	},
	
	handleEvent : function(event) {
	  // dispatch the event to the right method based on its type
	  //console.log("[OVERLAY] handle event:"+ event.type);
	  switch (event.type) {
	    case 'touchstart' :
	      this.onTouchStarted(event);
	      break;
	    case 'touchmove' :
	      this.onTouchMoved(event);
	      break;
	    case 'touchend' :
	      this.onTouchEnd(event);
	      break;
	    case 'webkitTransitionEnd' :
	      //
	     break;	    
	   	case 'resize' :
	      this.onWindowSize();
	     break;	  
	  }
	},
	
	
	// !Events AND Callbacks
	onKeyClick: function(event) {
        var keycode = event.keyCode;
		//alert('keycode('+keycode+') pressed');
        var escapeKey;
        if (event.DOM_VK_ESCAPE) {  // mozilla
            escapeKey = event.DOM_VK_ESCAPE;
        }else{ // ie
            escapeKey = 27;
        };

        var key = String.fromCharCode(keycode).toLowerCase();
        
        if(key.match(/x|o|c/) || (keycode == escapeKey)) this.closeOverlay();
        
    },
    
    onOrientationChange : function(){
    	//console.log("[OVERLAY] onOrientationChange")
 		this.setSize();
 		this._resize(this.currentFile); 
 		this._center(this.holder); 
    },
    
    onWindowSize: function(){
    	console.log("[OVERLAY] onWindowSize");
    	this.setSize();
    	this._center(this.layout);
    },
    
    onContentEntry : function(){
    	//new Effect.Appear(this.close, { duration: 0.2, from: 0.0, to: 1});//**
		//if(this.displayType == 'video' && this.options.movieControlType != 'swf') this.showMovie();
    },
    	

	// !OPEN/CLOSE
	/*
		@ if there is an overlay - reveal it
		@ reveal the holderarea
		@ reveal the shadow for holder if there is one
	*/
	//---------------
	openOverlay:function(){
		//alert('NSOverlay: openBox -->'+this.overlay);	
		this.closed = false;
		//var self = this;
		//**this.onKeyClick = this.onKeyClick.bindAsEventListener(this);
		
		(this.content)? this.prepToLoad() : '';
	},
	
	closeOverlay:function(){
	
		// ** document.stopObserving('keydown', this.onKeyClick);
		// ** Event.stopObserving(window, 'resize', this.onWindowSize.bind(this));
		if(null != this.loader) this.hideLoader();
		
		if(this.fileType == 'swf' || this.options.movieControlType == 'swf') swfobject.removeSWF("nsflash");// if a swf need to remove
		
		if(null != this.holder){
			this.holder.empty();
			this.holder.dispose();
		};
		
		this.fireEvent('closed');
		
		//$(document.body).onorientationchange = null;
		this.removeAfterClose();

	},
	
	removeAfterClose:function(){
		
		if(null != this.overlay) this.overlay.dispose();
		this.cleanUp();
	},
	
	cleanUp : function(){
		//alert('cleanUp');
		this.options = {};
		this.content = null;
		this.currentRequest = null;
		this.currentResponse = null;
		this.isMoviePlaying = false;
		this.movie = null;
		this.closed = true;
		this.fileReady = false;
		this.contentCnt = null;
		this.overlay = null;
		this.holder = null;
		this.loader = null;
	},
	
		//----------------
	// !Ready To Show
	// #1
	loadComplete:function(){
		//alert('loadComplete');
		this.fileReady = true; //the file is loaded and ready to be showed (see next_prev_aux())
		
 		if(this.closed){ return; };//if you close and an onload event is still running

 		var fileSize = new Hash();// store the size of the loaded media 	
 		var targetSize = {};// calculate size plus any passed padding, border, etc
 		var targetPos = {};// object passed to morph position of holder
 		var b;
 		var p = this.options.contentPadding;// store calaculate padding to add
 		var d;// store file dimesions
 		var holderDim = this.holder.getSize();
 		var addSize = (this.options.contentPadding*2);//  + (this.options.contentBorderWidth*2) amount to add to file size

 		
 		if(p != 0) this.contentCnt.setStyle({padding:p+'px'}); 			

 		if(this.options.displayType == 'asset' && !this.options.fixedSize){//is an image file  !file.retrieve('width')
 			var d = this.currentFile.getSize();//			
 			fileSize.set({ 'height':d.y, 'width':d.x});		
		
		} else if(this.options.displayType == 'video'){// movie
 			fileSize.set({ 'height':this.movieH, 'width':this.movieW });
 			

 		}else if(this.options.displayType == 'webpage'){// external url
 			fileSize.set({ 'height':this.iframeH, 'width':this.iframeW});// additional for scrollers		
	
 		} else {//non-image or fixed size image, need to use options value
 			fileSize.set({ 'height':this.options.contentHeight, 'width':this.options.contentWidth });
 		};
 		
		
		//fileSize = fileSize.toObject();// convert hash to object
		
		// check to see if holder is not the same size as file loaded
		// the movies and iframes already have there w x h prefigured
		targetSize.width = ((this.options.displayType == 'video' && this.options.movieControlType != 'swf') || this.options.displayType == 'webpage')? this.options.contentWidth : (fileSize.width + addSize);// 
		
		targetSize.height = ((this.options.displayType == 'video' && this.options.movieControlType != 'swf') || this.options.displayType == 'webpage')? this.options.contentHeight : (fileSize.height + addSize); 
 		
 		//if(this.options.displayType == 'webpage') targetSize.height += this.options.contentBorderWidth;		
 		
 		if((fileSize.get('width') != holderDim.x || this.options.fixedSize) && !this.options.position){
			targetPos.marginLeft = -(targetSize.width/2)+'px';
 		}; 
 		
 		
 		if((fileSize.get('height') != holderDim.y || this.options.fixedSize) && !this.options.position){
 			targetPos.marginTop = -(targetSize.height/2)+'px';
 		};				
		
		// do we need to check against the window size?
		
		//targetSize.width = targetSize.width;// +'px'
		//targetSize.height = targetSize.height;//+'px' 
		
		if(this.options.contentBorderWidth != 0 ){
			b = this.options.contentBorderWidth + 'px solid ' + this.options.contentBorderColor;
			this.layout.setStyles({border:b});//contentCnt
		};	
		
		// change the size of layout area and (and shaodw by default shadow) move holder to keep things centered
 		//console.log('type:'+this.options.displayType+' , width:'+targetSize.width+', height:'+targetSize.height);	
		//this.layout.setStyles(targetSize);
		this._resize(this.layout, targetSize.width, targetSize.height);
		//this._center(this.layout);
		this.showContent();

	},

	// #3 - either after morph - or directly
	showContent:function(){
		//&& this.options.fixedSize
		// the catch here is if we are on a portable device even if it is saying keep a fixed size
		// we need to resize so it fits
		console.log('showContent  this.options.displayType='+this.options.displayType+', this.options.contentWidth:'+this.options.contentWidth+', this.options.contentHeight:'+this.options.contentHeight);
		if(this.options.displayType != 'webpage' && this.options.displayType != 'html' && this.fileType != 'swf' && this.options.displayType != 'video' ){
		 		// make image fit inside passed content width and height
		 		// check if new sizes are greater than max
				//this.contentCnt.setStyles({width:this.options.contentWidth+'px', height:this.options.contentHeight+'px' });
				this._resize(this.contentCnt,this.options.contentWidth+'px', this.options.contentHeight+'px');
			 	
				this._resize(this.currentFile);
		};
		
		//this.contentCnt.setStyle({visibility:'visible', opacity:0.0});
		//new Effect.Opacity(this.contentCnt,{ duration: this.options.entryDuration, from: 0.0, to: 1, afterFinish:this.onContentEntry.bind(this)});
		if(this.options.movieControlType == 'swf') this.hideLoader();//this.options.displayType != 'video' || 
		this.onContentEntry();
		this._center(this.holder);
	},
	
	// !load related methods
	showLoader : function(){
		//this.loader.appendChild(new Element('div', {'id':'animation' }));//new Element
	},
	
	hideLoader : function(){
		//
	},

	prepToLoad:function(fileObj){
		this.fileReady = false;
		//this.showLoader();
		
		//console.log('[OVERLAY] prepToLoad -'+this.options.displayType);
		switch(this.options.displayType){
			case 'webpage' :
				this.loadPage(this.content);
				break;
			case 'html' :
				this.loadHTML(this.content);
				break;
			
			case 'video' :
				this.loadMovie(this.content);
							
				break;
			
			default :
				if(this.fileType == 'swf'){
					this.loadSwf(this.content);// need to test for swfobject else fail gracefully?
				}else{
					this.loadImage(this.content);
				}
				break;			
		};
		

	},

	//------------------------------------
	// !unique loading actions

	loadImage:function(f){
		//var self = this;
		//var c = new Element('img', {'id':'nsImg'});
		var imageAsset = new Asset.image(f, { onload:function(img){
			img.inject(this.contentCnt);
			this.currentFile = img;
			this.loadComplete();
		}.bindWithEvent(this)});
		
	},

	loadSwf : function(f, isVid){
		var sNameId = 'nsflash';
		var c = new Element('div', {'id':sNameId, 'html':'<h2>Flash Content.</h2>'});
		this.contentCnt.appendChild(c);
		if(f.indexOf('vimeo.com') != -1 && f.indexOf('autoplay') == -1) f += '&amp;autoplay=1';
		var att = {data:f, width:this.options.contentWidth, height:this.options.contentHeight};// +'px'+'px'will occupy what ever space set by content
		var params = {wmode : "transparent", menu : false, allowFullScreen: true, allowScriptAccess: 'always', base: this.options.siteURL};//
		//
/*
		if(isVid){
			att.data = this.options.baseURL+'swfs/singleMedia.swf';
			if(f.indexOf('http://') == -1) f = this.options.siteURL+f;
			params.flashvars = 'file='+f+'&groundcolor='+this.options.contentColor+'&color='+this.options.siteColor+'&w='+this.options.contentWidth+'&h='+this.options.contentHeight;			
			//+this.movieWthis.movieH
		};
*/
		
		if(f.indexOf('pictage.com') != -1){
			params.base = 'http://www.pictage.com/photographers/static/static/slideshows/swf/.';// sets base for pictage
		};
		// 
		if(null != swfobject && (swfobject.hasFlashPlayerVersion(this.options.flashVersion) || f.indexOf('youtube.com') != -1 )){
			swfobject.createSWF(att, params, sNameId);
		};
		this.currentFile = c;
		//alert('Load Flash');
		this.loadComplete();
	},


	loadHTML : function(s){
		var c = new Element('div', {'id':'bbHtml'}).inject(this.contentCnt);
			c.set('html',s);
		this.currentFile = c;
		this.loadComplete();
	},

	loadPage : function(f){
		var c = new IFrame({ 'src': f,
		    'styles': {
		        width: this.iframeW+'px',
		        height: this.iframeH+'px',
		        scrolling: this.options.iframeScrollers,
		        border: '0px solid #ffffff'
		    }
		}).inject(this.contentCnt);
		//console.log('[OVERLAY] load Page() frame w:'+this.iframeW+', h:'+this.iframeH);
		this.currentFile = c;
		this.loadComplete();
	},


	// !Movie Related

	loadMovie : function(f){
		// we have the option of different controllers
		// if movieControlType == 'swf' then we will do a 
		// may want the panel to establish the size?
		//var c = new Element('div',{'id':'nsMovie'});
		//console.log('[OVERLAY] loadMovie -'+this.content);	
		// depending on orientation- need to set just one attribute? so aspect ratio is maintained
		// need to set the width x height on element ipad doesn't seem to change from default //
		var vid = new Element('video',{id:'moviepanel','src':this.content, 'width':this.movieW, 'height': this.movieH, 'controls':'controls', 'autobuffer':true});//

 		this.contentCnt.appendChild(vid);
 		//if(this.options.movieAutoPlay) vid.play();
		this.currentFile = vid;
		this._resize(vid, this.movieW, this.movieH);
		this.loadComplete();// could set a listenre fr when enough is loaded to play...

	}
	


});

