/** 
* Preloader class for web-T::CMS
*
* @author goshi
* @version 2.1
* @package javascript::share
*
* Changelog:
* 	2.1		25.08.10/goshi	fixing in correctPos is parent is body
* 	2.0		04.08.10/goshi	add fixing position of the some types of the loader
* 	1.9		30.07.10/goshi	add progressbar mode
* 	1.82	24.05.10/goshi	fix bug with negative margin-top
* 	1.81	13.05.10/goshi	fix init image after addParams 
* 	1.8		10.04.10/goshi	add correctPos method, add custom loader name 
* 	1.7		27.03.10/goshi	now constructor can handle objects 
* 	1.61	17.03.10/goshi	fix bug with init
* 	1.6	06.03.10/goshi	add share dir for loaders, remove from constructor images initialization
* 	1.5	02.07.09/goshi	added 'float-mini' mode
* 	1.4	13.05.09/goshi	added 'mini' mode, add parsing skin_img_dir
* 	1.3	02.05.09/goshi	fixes bug with opacity in IE
* 	1.2	17.04.09/goshi	add custom alpha setting
* 	1.1	07.04.09/goshi	add _src property
*/

/**
* @constructor
*/
function pphpPreLoader(params){
	this._init(params);
}

pphpPreLoader.prototype = {

	_items : null,
	_mode : 'standart',		// standart mode for showing - can be 'standart','float','float-mini' and 'mini' (mini is like a standart, but using mini image)
	_src : null,			// image source 
	_src_mini : null,		// image mini source
	_loader_name : "loader.gif",	// loader filename
	_loader_mini_name : "loader_mini.gif",	// mini loader filename
	_skin_img_dir : null, 
	_alpha : 0.8,			// alpha transparency, from 0 to 1
	_text : 'Updating...',	// text, that showing with loader
	_old_height : 0,
	_animate_speed: 25, 
	_animate_step: 10, 
	
	/* constructor */
	_init: function(params){
		
		this.addParams(params);				
		this._items = {};
						
	},
	
	addParams : function (params){
	
		if (typeof params != "undefined"){
			for (var i in params){
				if (typeof this['_'+i] != "undefined")
					this['_'+i] = params[i];
			}

			if (!this._skin_img_dir)
				this._skin_img_dir = skin_img_dir+share_dir;

			// reinit images
			if (typeof params['skin_img_dir'] != 'undefined' || typeof params['loader_name'] != 'undefined'){
				this._init_images();
			}
			
		}
	},
	
		
	_init_images : function(){
		this._src = new Image();
		this._src_mini = new Image();
		this._src.src = this._skin_img_dir + this._loader_name;
		this._src_mini.src = this._skin_img_dir + this._loader_mini_name;
		
	},
	
	_applyAlpha : function(obj, alpha){
	
		if (obj && obj.style){
			obj.style.opacity = obj.style["'-khtml-opacity"] = obj.style["-moz-opacity"] = alpha;
			if (/MSIE/.test(navigator.userAgent)) {
				obj.style.filter = alpha === '' ? '' : "alpha(opacity=" + (alpha * 100) + ")";
				if (!obj.currentStyle || !obj.currentStyle.hasLayout)
					obj.style.display = 'inline-block';
			}
		}	
	},
	
	_animate : function (ticket, param, value){
		//portal.debug.dump('animate!!!!'+ticket, true);
		
		var obj = $_('progressbar_'+ticket);
		//alert((typeof obj)+'---'+obj);
		
		if (typeof obj == 'object' && obj !== null){
			var an = function(){
				portal.loader._animate(ticket, param, value);
			}
			//portal.debug.dump('run', true);
			// check for presenting object style
			if (typeof obj.style == 'undefined'){ setTimeout(an, portal.loader._animate_speed); return;}
		
		//portal.debug.dump(obj+'---'+param+'---'+obj.id+'---'+typeof(obj.style)+'---'+obj.style[param], true);
			if (obj.style[param] == '') obj.style[param] = 0;
			
			//portal.debug.dump(parseInt(obj.style[param])+'---'+parseInt(value), true);
			if (parseInt(obj.style[param]) < parseInt(value)){
				//portal.debug.dump(parseInt(obj.style[param]) < parseInt(value), true);
				var step = parseInt(obj.style[param]) + portal.loader._animate_step;
				step > parseInt(value) ? step = parseInt(value) : '';
				
				obj.style[param] = step + (value.indexOf('%') >= 0 ? '%' : 'px'); 
				
				setTimeout(an, portal.loader._animate_speed);
			} else {
				//portal.debug.dump('call next', true);
				portal.loader._runCallback(ticket, true);
			}
		} //portal.debug.dump('no object: '+'progressbar_'+ticket+'; '+(typeof obj)+'; '+obj+'; dump'+$_('progressbar_'+ticket), true);
	},
	
	_addCallback : function(ticket, callback){

		if (this._items[ticket] && typeof this._items[ticket]['callbacks'] == 'object'){
			this._items[ticket]['callbacks'][this._items[ticket]['callbacks'].length] = callback;
			
			// if one element in queue - run it
			//portal.debug.dump('add: '+this._items[ticket]['callbacks'].length, true);
			if (this._items[ticket]['callbacks'].length == '1'){
				this._runCallback(ticket);
			}
		}
	
	},
	
	_runCallback : function(ticket, clear_last){
		//portal.debug.dump('_runCallback: '+ticket, true);

		if (portal.loader._items[ticket] && typeof portal.loader._items[ticket]['callbacks'] == 'object'){

			if (typeof clear_last != 'undefined' && clear_last){
				// because delete dont realy delete element - create new array
				var newarr = [];
				for (var i=1; i<portal.loader._items[ticket]['callbacks'].length; i++){
					newarr[i-1] = portal.loader._items[ticket]['callbacks'][i];
				}
				portal.loader._items[ticket]['callbacks'] = newarr;
				//portal.debug.dump('run next: '+portal.loader._items[ticket]['callbacks'].length, true);

			}
			
			if (typeof this._items[ticket]['callbacks'][0] == 'function'){
				this._items[ticket]['callbacks'][0]();
			}
		}
	
	},
	
	/** correct position of the loader */
	_correctPos : function(ticket, self, mode){
	
		if (typeof self == 'undefined' || !self)
			self = this;

		var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
	
		switch (mode){
		
		case 'float': 
		case 'progress':
			var layer_bg = $_('loader_'+ticket);
					
			layer_bg.style.width = layer_bg.parentNode.scrollWidth + 'px';//document.body.scrollWidth + 'px';
			layer_bg.style.height = (layer_bg.parentNode.tagName == 'BODY' ? getDocumentHeight() : layer_bg.parentNode.offsetHeight) + 'px';
	
			//this._main_layer.style.left = (cX - this._main_layer.offsetWidth)/2 + 'px';
			var cY = getClientHeight();//ev.clientY;
	
			if (layer_bg.parentNode.tagName == 'BODY')
				self._items[ticket]['loader_obj'].style.top = (scrollTop + (cY - self._items[ticket]['loader_obj'].offsetHeight)/2) + 'px';
			break;
			
		case 'float-mini':
			$_('loader_'+ticket).style.top = scrollTop+'px';
			break;
		
		default:
			break;
		}
	},
			
	create : function(objid, params){
	
		this.addParams(params);
		
		// if not found images - create them
		if (this._src == null){
			this._init_images();
		}
		
		var tmpdt = new Date;
		// generate uniq id - we need to initialize date object each time for unique id
		var ticket = tmpdt.getTime();
		
		
		var tmode = (typeof params != "undefined" && params.mode ? params.mode : this._mode);
		var alpha = (typeof params != "undefined" && params.alpha ? params.alpha : this._alpha);
		var obj = ((typeof(objid)).toLowerCase() == "string" ? $_(objid) : ((typeof(objid)).toLowerCase() == 'object' && objid != null ? objid : document.body));
		
		this._items[ticket] = {'mode' : tmode, 'owner' : obj};
		
		// saving old height of the object height
		this._old_height = obj.offsetHeight;
		
		switch (tmode){
		
		case 'float' :
		case 'float-mini' :
			var el = elem('div', {'class' : (tmode == 'float' ? 'loader-abs' : 'loader-mini-abs'), 'id' : 'loader_'+ticket});
			
			var el_inn = elem('div', {});
			this._applyAlpha(el_inn, alpha);
			
			el.appendChild(el_inn);
			var ld_obj = elem('img', {'src' : this._src.src, 'class' : 'ldr'});
			this._items[ticket]['loader_obj'] = ld_obj;
			el.appendChild(ld_obj);
			if (tmode == 'float-mini'){
				el.appendChild(elem('span', false, false, this._text));	
			}
			
			obj.appendChild(el);
			
			// correct position of the object
			//if (tmode == 'float')
			this._correctPos(ticket, this, tmode);
			break;
					
		case 'mini' :
			obj.innerHTML = '<span class="loader" id="loader_'+ticket+'"><img src="' + this._src_mini.src + '" class="ldr" /></span>';
			//this._correctPos(ticket);
			break;
			
		case 'progress' :
			var el = elem('div', {'class' : 'loader-abs', 'id' : 'loader_'+ticket});
			var el_inn = elem('div', {});
			this._applyAlpha(el_inn, alpha);
			el.appendChild(el_inn);
			
			var el_inn = elem('ins', {'class' : 'progressbar'});
			this._items[ticket]['loader_obj'] = el_inn;
			
			el_inn.appendChild(elem('del', {'id' : 'progressbar_'+ticket}));
			el.appendChild(el_inn);
			
			obj.appendChild(el);

			// correct position of the object
			this._correctPos(ticket, this, tmode);
			
			// apply params to the ticket
			// checking for ajax instance
			if (typeof params != 'undefined' && typeof params['ajaxinstance'] == 'object' && typeof params['ajaxinstance'].onreadystatechange == 'function'){
				
				this._items[ticket]['_ajaxinstance'] = params['ajaxinstance'];
			
				// overriding readystate change function with saving old callback
				this._items[ticket]['_ajaxstate'] = 0;
				this._items[ticket]['callbacks'] = [];
				this._items[ticket]['_ajaxinstancecallback'] = this._items[ticket]['_ajaxinstance'].onreadystatechange;
				var athis = this;

				this._items[ticket]['_ajaxinstance'].onreadystatechange = function(){

					if (athis._items[ticket]['_ajaxinstance'].readyState > athis._items[ticket]['_ajaxstate']){
						athis._items[ticket]['_ajaxstate'] = athis._items[ticket]['_ajaxinstance'].readyState;
						
						athis._addCallback(ticket, function(){athis._animate(ticket, 'width', parseInt(athis._items[ticket]['_ajaxstate'])*25+'%');});
						
						//$_('progressbar_'+ticket).style.width = parseInt(athis._items[ticket]['_ajaxstate'])*25+'%';
						if (typeof athis._items[ticket]['_ajaxinstancecallback'] == 'function'){
							athis._items[ticket]['_ajaxinstancecallback']();
						}
					}	
				}

			}

			break;

		case 'standart' :
		default:
			obj.innerHTML = '<div class="loader" id="loader_'+ticket+'"><img src="' + this._src.src + '" class="ldr" /></div>';
			//this._correctPos(ticket);
			break;
		}
		
		return ticket;
	
	},
	
	destroy : function(ticket){
	
		if (this._items[ticket]){
			switch (this._items[ticket].mode){
			case 'float':
			case 'float-mini':
				this._items[ticket].owner.removeChild($_('loader_'+ticket));
				delete this._items[ticket];

				break;
				
			case 'progress': 
				var athis = this;
				this._addCallback(ticket, function(){
					athis._items[ticket].owner.removeChild($_('loader_'+ticket)); delete athis._items[ticket]; });	
				break;
				
			case 'standart':
			default: 
				this._items[ticket].owner.innerHTML = '';
				delete this._items[ticket];
				break;
			}
			
			return null;
		}
	
	}	

}

// adding preloader to portal
portal.loader = new pphpPreLoader({'mode' : 'standart'});
