/**
 * Zfse_FoldingMedia
 * 
 * @param {string} id Media container ID
 * @param {object} media Media type
 * @param {string} title Title
 */
Zfse_FoldingMedia = function(id, media, title){

	this.id = id;
	this.media = media;
	this.title = title;
	
	this._container = null;
	this._folded = true;
	this._effect = 'slow';
	this._currentEffect = null;
	
	/**
	 * Folds media into view
	 * 
	 * @param {string} effect Folding effect
	 */
	this.fold = function(effect){
		if(this._folded) return false;
		
		if(!effect) effect = this._effect;
		
		var media = this.media;
		if(this.media.onBeforeFold) this.media.onBeforeFold();
		var f = typeof this.media.onAfterFold == 'function' 
				? function(){media.onAfterFold();} 
				: function(){};
		
		$(this._container).toggle(effect, f);
		
		this._folded = true;
		this._currentEffect = effect;
		return true;
	};
	
	/**
	 * Unfolds media
	 */
	this.unFold = function(){
		if(!this._folded) return false;
		
		var effect = this._currentEffect || this._effect;
		var media = this.media;
		
		if(media.onBeforeUnFold){
			media.onBeforeUnFold();
		}
		
		var f = typeof media.onAfterUnFold == 'function' 
				? function(){media.onAfterUnFold();} 
				: function(){};
		
		$(this._container).toggle(effect, f);
		this._folded = false;
		
		return true;
	};
	
	/**
	 * Sets media position on X and Y coordinates relative
	 * to document body
	 * 
	 * @param {int} left
	 * @param {int} top
	 * @return {boolean}
	 */
	this.setPosition = function(left, top){
		this._container.style.left = /^[0-9]*$/.exec(left) ? left+'px' : left;
		this._container.style.top = /^[0-9]*$/.exec(top) ? top+'px' : top;
	};
	
	/**
	 * Returns boolean true if media is folded,
	 * false if unfolded
	 * 
	 * @return {boolean}
	 */
	this.isFolded = function(){
		return this._folded;
	};
	
	/**
	 * Returns media width in pixels
	 * 
	 * @return {int}
	 */
	this.getMediaWidth = function(){
		var img = $('img',this._container).get(0);
		return img ? img.width : null;
	};
	
	/**
	 * Returns media height in pixels
	 * 
	 * @return {int}
	 */	
	this.getMediaHeight = function(){
		var img = $('img',this._container).get(0);
		return img ? img.height : null;
	};
	
	/**
	 * Returns media outer width in pixels
	 * 
	 * @return {int}
	 */	
	this.getOuterWidth = function(){
		return this._outerWidth;
	};
	
	/**
	 * Returns media outer height in pixels
	 * 
	 * @return {int}
	 */	
	this.getOuterHeight = function(){
		return this._outerHeight;
	};
	
	/**
	 * Returns media type
	 * 
	 * @return {string}
	 */	
	this.getMediaType = function(){
		return this.media.type;
	};
	
	/**
	 * Resets media at its initial state and calculates
	 * its current outer width and height
	 * 
	 * @return {string}
	 */		
	this.reset = function(){
		var c = this._container;
		
		this._outerWidth = $(c).width();
		this._outerHeight = $(c).height();

		this.unFold();
	};
	
	/**
	 * Constructor
	 * 
	 * Creates a container element, positions it on the document so
	 * that it is hidden but its dimensions can be read. Calls media's
	 * onload-callback.
	 */		
	this._construct = function(){
		var content;
		var c = document.createElement('div');
		c.style.position = 'absolute';
		c.style.zIndex = 1000;
		c.style.top = '-2000px';
		c.style.left = '-2000px';
		c.className = 'zfse_foldingMedia';
		c.id = this.id;
		
		var p = document.createElement('div');
		p.className = 'zfse_foldingMediaPadder';
		c.appendChild(p);

		content = this.media.render();
		if(typeof content == 'object'){
			p.appendChild(content);
		}
		else{
			p.innerHTML = content;
		}
		
		if(this.title){
			var t = document.createElement('h6');
			t.innerHTML = this.title;
			p.appendChild(t);
		}
		
		document.body.appendChild(c);
		this._container = c;
		
		if(this.media.setOnLoad){
			var obj = this;
			var f = function(){obj.reset();};
			this.media.setOnLoad(f);
		}
		else{
			this.reset();
		}
	};
	
	this._construct();
};

/**
 * Media event type
 * 
 * @var {string}
 */
Zfse_FoldingMedia.OPT_EVENT_TYPE = 'eventType';

/**
 * Onclick event
 * 
 * @var {string}
 */
Zfse_FoldingMedia.EVENT_TYPE_CLICK = 'click';

/**
 * Onmouseover event
 * 
 * @var {string}
 */
Zfse_FoldingMedia.EVENT_TYPE_HOVER = 'hover';

/**
 * Array of document's folding media elements
 * 
 * @var {array}
 */
Zfse_FoldingMedia._elements = new Object();

/**
 * Initializes Zfse_FoldingMedia controls
 * 
 * This method reads all folding medias from current document,
 * creates Zfse_FoldingMedia objects and assigns their events.
 * 
 * This method should be called on document load.
 * 
 * @param {array} options 
 * @return
 */
Zfse_FoldingMedia.init = function(options){
	
	var options = typeof options == 'undefined' ? new Object() : options;
	var elems = $('a.zfse_foldingMedia').get();
	var medias = new Array();
	
	var eventType = options[Zfse_FoldingMedia.OPT_EVENT_TYPE] || Zfse_FoldingMedia.EVENT_TYPE_CLICK;

	for(var id=0;id<elems.length;id++){
		var media = Zfse_FoldingMedia.createMedia('zfse_foldingMedia_'+id, elems[id], options);
		if(!media) continue;
		
		medias[id] = media;
		
		//add class by media type
		$(elems[id]).toggleClass('zfse_foldingMedia-'+media.getMediaType(), true);
		
		eval('var f = function(e){Zfse_FoldingMedia.toggleMedia(medias['+id+'], e.pageX, e.pageY);return false;}');
		
		if(eventType == 'hover'){
			eval('var fold = function(e){Zfse_FoldingMedia.fold(medias['+id+'], e.pageX, e.pageY);return false;}');
			eval('var unFold = function(e){Zfse_FoldingMedia.unFold(medias['+id+']);return false;}');
			
			$(elems[id]).bind('mouseenter', fold);
			$(elems[id]).bind('mouseleave', unFold);
		}
		else{
			$(elems[id]).bind(eventType, f);
		}
	}
};

/**
 * Creates a new Zfse_FoldingMedia based on given ID, DOM element
 * and media options
 * 
 * @param {string} id ID for new Zfse_FoldingMedia
 * @param {object} element DOM element
 * @param {array} options Array of options
 * @return Zfse_FoldingMedia
 */
Zfse_FoldingMedia.createMedia = function(id, element, options){
	var title = element.title || element.name || null;
	var url = element.href || element.alt;
	var media, type;
	
	type = Zfse_FoldingMedia.getMediaTypeByUrl(url, id+'_content', title, options);
	if(type){
		media = new Zfse_FoldingMedia(id, type, title);
		Zfse_FoldingMedia._elements['t'+id] = media;
	}
	
	return media;
};

/**
 * Returns media type by media URL
 * 
 * @param {string} url
 * @param {string} id
 * @param {string} title
 * @param {array} options
 * @return {string} 
 */
Zfse_FoldingMedia.getMediaTypeByUrl = function(url, id, title, options){
	var match = /\.([a-z0-9]+)(\?|$)/i.exec(url);
	var ext;
	
	if(match[1]){
		ext = match[1];

		switch(ext){
			case 'jpg':
			case 'jpeg':
			case 'png':
			case 'gif':
			case 'bmp':
				return new Zfse_FoldingMedia_Image(id, url, title);
			break;
			case 'flv':
				var opts = {
					width	: 640,
					height	: 500,
					image	: Zfse.getSetting('imageUri') + '/FoldingMedia/playMovie.jpg' 
				};

				if(options.flv){
					for(var key in options.flv){
						opts[key] = options.flv[key];
					}
				}
				
				return new Zfse_FoldingMedia_Flv(id, url, title, opts);
			break;
			default:
				return null;
			break;
		}
		
	}
	else return null;
};

/**
 * Toggles (folds/unfolds) media based on its current state using
 * given mouse coordinates
 * 
 * @param {Zfse_FoldingMedia} media
 * @param {int} mouseX
 * @param {int} mouseY
 * @return
 */
Zfse_FoldingMedia.toggleMedia = function(media, mouseX, mouseY){
	
	if(media){
		if(media.isFolded()){
			Zfse_FoldingMedia.unFold(media);
		}
		else{
			Zfse_FoldingMedia.unFoldAll();
			Zfse_FoldingMedia.fold(media, mouseX, mouseY);
		}
	}
};

/**
 * Folds media
 * 
 * @param {Zfse_FoldingMedia} media
 * @param {int} mouseX
 * @param {int} mouseY
 */
Zfse_FoldingMedia.fold = function(media, mouseX, mouseY){
	var x = 0, y = 0;
	var offsetX = 10;
	var offsetY = 10;
	
	var marginX = 10;
	var marginY = 10;
	
	$(window).scrollTop();
	
	var dw = $(document.body).width()+$(window).scrollLeft();
	var dh = $(document.body).height()+$(window).scrollTop();
	
	var w = media.getOuterWidth();
	var h = media.getOuterHeight();
	
	if(mouseX+offsetX+w+marginX > dw){
		x = mouseX-offsetX-w-marginX;
		if(x < 0) x = marginX;
	}
	else{
		x = mouseX+offsetX;
	}
	
	if(mouseY+offsetY+h+marginY > dh){
		y = mouseY-offsetY-h-marginY;
		if(y < 0) y = marginY;
	}
	else{
		y = mouseY+offsetY;
	}
	
	media.setPosition(x, y);
	media.fold();
	
	$(document.body).bind('click.zfse_foldingMedia', function(){Zfse_FoldingMedia.unFoldAll();});
};

/**
 * Unfolds media
 * 
 * @param {Zfse_FoldingMedia} media
 * @param {int} mouseX
 * @param {int} mouseY
 */
Zfse_FoldingMedia.unFold = function(media){
	media.unFold();
	$(document.body).unbind('click.zfse_foldingMedia');
};

/**
 * Unfolds all media
 */
Zfse_FoldingMedia.unFoldAll = function(){
	for(var key in Zfse_FoldingMedia._elements){
		Zfse_FoldingMedia.unFold(Zfse_FoldingMedia._elements[key]);
	}
};