/**
 * Copyright (c) 2008 Andreas Timm | symmetrics gmbh (http://www.symmetrics.de)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * $CreateDate: 2007-09-01 00:00:00 +0001 (Thu, 01 Sep 2007) $
 *
 * Version: 0.01
 * 
 * @author Andreas Timm <at@symmetrics.de>
 *
 * Requires: jQuery 1.2.4+
 **/
var dAux = function()
{
	this.w_width;			//windows width
	this.w_height;			//windows height
	
	this.scr_width;			//screen width
	this.scr_height;		//screen height
	
	this.scroll_left;		//scroll left
	this.scroll_top;		//scroll top
	
	this.CSS1Compat = 1 ;	//for windows width calculation

	this.flexblt_func = false ; // function for add to flexibility

	this.input_focus_vars = new Object ;
	this.load_progress_vars = new Object ;

	this.temp = new Object ;

	this.data_load_init = new Object ;
	this.load_modules_init = new Array ;

	//-------------------------------------
	// collision and correction
	//-------------------------------------

	this.mouse_mover_box_vars = 
	{
		init: false,
		over: 0
	} ;

	this.mouse_wheel_func = new Function ;


	//-------------------------------------
	// init
	//-------------------------------------


	this.init = function ()
	{
//		//******************
//		this.temp = document.getElementById("temp1") ;
//		//******************
		
		if ( document.compatMode=='CSS1Compat' && !window.opera )
			this.CSS1Compat = 0 ;

		this.setWindowParams() ;

//		this.flexibility () ;
//		
//		//events
//		$(window).resize ( function() {
//			dAux.flexibility () ;
//		}) ;
	} ;








	/**
	 * load modules
	 *
	 * @param	String		module:
	 * @param	Oject		param:
	 **/
	this.load_module = function ( module, param )
	{
		var module_data = data_modules[module] ;

		if ( module_data === undefined )
			return false ;

		$.getScript
		(
			module_data[0],
			function(){
				if ( param !== undefined )
					window[module].init ( param ) ;
			}
		);

	} ;





	//-------------------------------------
	// design
	//-------------------------------------

	this.setWindowParams = function ()
	{
		this.w_width = this.CSS1Compat ?
			document.body.clientWidth : document.documentElement.clientWidth ;
		this.w_height = this.CSS1Compat ?
			document.body.clientHeight  : document.documentElement.clientHeight ;
			
		this.scr_width = this.CSS1Compat ?
			window.innerWidth : document.documentElement.clientWidth;
		this.scr_height = this.CSS1Compat ?
			window.innerHeight : document.documentElement.clientHeight;

		this.setWindowScroll() ;
	}

	this.setWindowScroll = function ()
	{
		this.scroll_left = this.CSS1Compat ?
			window.pageXOffset : document.documentElement.scrollLeft;
		this.scroll_top = this.CSS1Compat ?
			window.pageYOffset : document.documentElement.scrollTop;
	}	

	this.flexibility = function ()
	{
		if ( this.w_width <= 1010  ) this.w_width = 1010 ;	
		if ( this.w_height <= 530  ) this.w_height = 530 ;
		
		if ( this.flexblt_func != false )
			this.flexblt_func() ;
	};





	//-------------------------------------
	// elements control
	//-------------------------------------




	/**
	 * move of elements
	 *
	 * @param	Object		v:
	 * 				String		id: id of element
	 * 				String		click_id:	id of click-element
	 * 										if undefined then click_id = id
	 * 				Number		width: (default=dAux.w_width)
	 * 				Number		height: (default=dAux.w_height)
	 * 				
	 **/
	this.elements_move = function ( v )
	{
		if ( v.click_id === undefined )
			v.click_id = v.id ;
			
		dAux.positions[v.id].p_width = v.width != undefined ?
			v.width :
			dAux.w_width ;
		
		dAux.positions[v.id].p_height = v.width != undefined ?
			v.height :
			dAux.w_height ;
		
		$("#"+v.click_id).mousedown(function( event ){

			var pos = $("#"+v.id).position() ;

			dAux.positions[v.id].x_d = event.pageX - pos.left ; 
			dAux.positions[v.id].y_d = event.pageY - pos.top ; 

			dAux.mouse_over_box ({
				action: "init",
				cursor: "move",
				func_move: function ( event ) {
	
					var x = event.pageX - dAux.positions[v.id].x_d ;
					var y = event.pageY - dAux.positions[v.id].y_d ;

					if ( x < 0 )
						x = 0 ;
					else if ( x > dAux.positions[v.id].p_width - $("#"+v.id).width() )
						x = dAux.positions[v.id].p_width - $("#"+v.id).width() ;
					
					if ( y < 0 )
						y = 0 ;
					else if ( y > dAux.positions[v.id].p_height - $("#"+v.id).height() )
						y = dAux.positions[v.id].p_height - $("#"+v.id).height() ;
									
					$("#"+v.id).css({ top : y, left : x });						
				},
				func_up: function () {
					dAux.mouse_over_box ({ action: "remove" }) ;
				}
			});

		});
	};



	/**
	 * mouse-events over box
	 * 
	 * @param	Object		v:
	 * 				String		action:		init|remove|reinit
	 * 				String		cursor:		cursor
	 * 				Function	func_move:	function by mousemove
	 * 				Function	func_up:	function by mouseup
	 * 				Function	func_down:	function by mousedown
	 */
	this.mouse_over_box = function ( v )
	{
		
		$("#mouse_overhead").focus();
		var	mover = document.getElementById("mouse_overhead") ;
		
		switch ( v.action )
		{
			case "init":

				this.disableSelection(document.body);

				this.setWindowParams();

				mover.style.left = dAux.scroll_left + "px";
				mover.style.top = dAux.scroll_top + "px";
				
				mover.style.width = dAux.scr_width + "px";
				mover.style.height = dAux.scr_height + "px";
				
				mover.style.display = "block";

//				mover.style.zIndex = 400;
				
//				if ( v.cursor !== undefined )
//					mover.style.cursor = v.cursor ;
				
				if ( browser_msie )
				{
//					$("#ie_noselect").css(css);
					document.getElementsByTagName("body")[0].onselectstart =
						function () { return false; } ;
				};

				if ( v.func_move !== undefined )
				{
					document.onmousemove = function ( e )
					{
						if ( browser_msie == true )
							e =
							{
								pageX: event.clientX + document.documentElement.scrollLeft,
								pageY: event.clientY + document.documentElement.scrollTop
							};
						
					 	v.func_move ( e ) ;
					} ;
				};

				if ( v.func_up !== undefined )
				{
					document.onmouseup = function ( e )
					{
						if 	( browser_msie == true )
							e =
							{ 
								pageX: event.clientX + document.documentElement.scrollLeft,
								pageY: event.clientY + document.documentElement.scrollTop
							};
					 	v.func_up ( e ) ;
					} ;
				};

				if ( v.func_down !== undefined )
				{
					mover.onmousedown = function ( e )
					{
						if 	( browser_msie == true )
							e =
							{ 
								pageX: event.clientX + document.body.scrollLeft,
								pageY: event.clientY + document.body.scrollTop
							};
					 	v.func_down ( e ) ;
					} ;
				};

//				mover.onmouseover = function ()
//				{
//					dAux.mouse_mover_box_vars.over++ ;
//					if ( dMain.mouse_mover_box_vars.over > 1 )
//						dAux.mouse_over_box ({ action: "remove" }) ;
//				};
					
				this.mouse_mover_box_vars.init = true ;
		
			break;
			case "remove":

				this.enableSelection(document.body);
				
				this.mouse_mover_box_vars.init = false ;
				this.mouse_mover_box_vars.over = 0 ;
				
				document.onmousemove = {} ;
				document.onmouseup = {} ;
				mover.onmousedown = {} ;
//				mover.onmouseover = {} ;
				
				mover.style.display = "none";
				if ( browser_msie )
				{
					$("#ie_noselect").css({display: "none"});
					document.getElementsByTagName("body")[0].onselectstart = {} ;
				};



			break;
			case "reinit":

				this.mouse_over_box ({ action: "remove" }) ;
				v.action = "init" ;
				this.mouse_over_box ( v ) ;
				return false ;

			break;
		}

	};





	this.wheel_switching = function ( v ) //c,func
	{
		if (window.removeEventListener)
			window.removeEventListener('DOMMouseScroll', this.mouse_wheel_func, false);
		window.onmousewheel = document.onmousewheel = {};

		if ( v.c != "stop" )
		{
			this.mouse_wheel_func = function(e){ dAux.wheel_control({e:e,func:v.func});} ;
			if (window.addEventListener)
				window.addEventListener('DOMMouseScroll', this.mouse_wheel_func, false) ;
			window.onmousewheel = document.onmousewheel = this.mouse_wheel_func ;
		};
	};
	

	this.wheel_control = function ( v ) //e:event,func:function
	{
		var delta = 0;
		if (!v.e) v.e = window.event;

		var mouse_x = 0 ;
		
		if ( jQuery.browser.mozilla )
			mouse_x = v.e.screenX ;
		else  if ( v.e.pageX )
			mouse_x = v.e.pageX ;
		else 
			mouse_x =
				v.e.clientX +
				( document.documentElement.scrollLeft || document.body.scrollLeft) -
				document.documentElement.clientLeft ;
		
		if (v.e.wheelDelta)
		{
			delta = v.e.wheelDelta/120;
			if (window.opera) delta = -delta;
		}
		else  if (v.e.detail)
			delta = -v.e.detail/3;
		
		if ( delta && v.func ) 
			v.func ({ delta:delta, x: mouse_x }) ;
		
		if (v.e.preventDefault) v.e.preventDefault();
		v.e.returnValue = false;
	};



	//-------------------------------------
	// help functions
	//-------------------------------------



	/**
	 * load data from server
	 * 
	 * 
	 * @param	Object		v:
	 * 				String		id: id
	 * 				Object		url: object for url
	 * 				Function	init: function bei init
	 * 				Function	success: function bei success onload
	 * 				Function	complete: (Boolean load)
	 **/
	this.data_load = function ( v )
	{
		v.url = dAux.object2url ( v.url ) ;
		
		if ( dAux.data_load_init[v.id] === undefined )
			dAux.data_load_init[v.id] = { init: null, cache: "" } ;
		
		if ( v.url != dAux.data_load_init[v.id].cache )
		{
			if ( v.init !== undefined )
				v.init() ;

			if ( dAux.data_load_init[v.id].init !== null )
				dAux.data_load_init[v.id].init.abort () ;
			
			dAux.data_load_init[v.id].cache = v.url ;

			dAux.data_load_init[v.id].init = $.ajax({
				type: "GET",
				url: "/",
				data: v.url,
				dataType: "json",
				success: function ( data )
				{
					dAux.data_load_init[v.id].init = null ;
					if ( v.success !== undefined )
						v.success ( data ) ;
					if ( v.complete !== undefined )
						v.complete( true ) ;
				}
			});
		}
		else if ( v.complete !== undefined )
			v.complete( false ) ;
	};
	
	



	/**
	 * get gradient
	 *
	 * @param	Array		c1: first RGB color
	 * @param	Array		c2: last RGB color
	 * @param	Number		n: count of gradients
	 * 					
	 * @return	Array		grad: array of RGB gradients (as Strings)
	 **/
	this.get_gradient = function ( c1, c2, n )
	{
		c1 = [32,85,140] ;
		c2 = [255,255,255] ;
		
		var d =
		[
			c2[0]-c1[0],
			c2[1]-c1[1],
			c2[2]-c1[2]
		] ;
		 
		var c = c1 ;

		var k ;
		var grad = new Array();

		n-- ;
		var i = 0 ;
		for ( i = 0; i <= n; i++ )
		{
//			k = Math.sin (  ( 2 * i - i * i / n ) * Math.PI / ( 2 * n ) ) ;
			k = Math.sin ( i * Math.PI / ( 2 * n ) ) ;
			c =
			[
				c1[0] + Math.round ( d[0] * k ),
				c1[1] + Math.round ( d[1] * k ),
				c1[2] + Math.round ( d[2] * k )
			] ;
			grad[i] = "rgb("+c[0]+","+c[1]+","+c[2]+")" ;
		}

		return grad ;
	} ;




	/**
	 * add or remove load progress indicator
	 *
	 * @param	Object		v:
	 * 				String		id:
	 * 				String		action: 
	 * 								init	(default)
	 * 								remove
	 * 				String		dom_id: (default=load_prg)
	 * 				Number		delay: (default=load_prg)
	 * 				Object		_parent:
	 * 				Object		css: css for indicator
	 * 				Number		x:
	 * 				Number		y:
	 * 				Function	func: after-function (by action == remove)
	 **/
	this.load_progress = function ( v )
	{
		if ( v._parent === undefined )
			v._parent = $("#main_load_progress") ;
		if ( v.dom_id === undefined )
			v.dom_id = "load_prg_id" ;

		if ( v.action == "init" )
		{
			if ( this.load_progress_vars[v.dom_id] === undefined )
				this.load_progress_vars[v.dom_id] =
				{
					ids: {}
				} ;
			
			if ( this.load_progress_vars[v.dom_id].show === true )
				return ;
			else
				this.load_progress_vars[v.dom_id].show = true ;
			
//			if ( v.delay !== undefined )
//			{
//				this.load_progress_vars[v.dom_id].dalay_init =
//					setTimeout ( function(){
//						if ( dAux.load_progress_vars[v.dom_id].ids[v.id] !== false )
//							dAux.load_progress({
//								
//							}) ;
//					}, v.delay ) ;
//			}
			
			v._parent.append( "<div id=\""+v.dom_id+"\" class=\"load_progress\"><div></div></div>" );

			var css = new Object ;
			if ( v.css !== undefined )
				css = v.css;
			
			css.display = "block" ;
			
			if ( v.x === undefined )
			{
				css.top = Math.round ( dAux.w_height / 2 ) - 16 ;
				css.left = Math.round ( dAux.w_width / 2 ) - 16 ;
			}
			else
			{
				css.top = v.y ;
				css.left = v.x ;
			}
			
			$("#"+v.dom_id).css(css);
		}
		else if ( v.action == "remove" )
		{
			this.load_progress_vars[v.dom_id].show = false ;
			this.load_progress_vars[v.dom_id].ids[v.id] = false ;
			var remove = true ;
			var i = "" ;
			for ( i in this.load_progress_vars[v.dom_id].ids )
				remove &= ! this.load_progress_vars[v.dom_id].ids[i] ;
			if ( remove )
				$("#"+v.dom_id).remove();
		}

	};
	

	this.object2url = function ( v )
	{
		var url = "" ;
		for ( var i in v )
			url += "&" + i + "=" + encodeURI ( v[i] ) ;
		return url ;
	};




	/**
	 * focus/blur for input field 
	 *
	 * @param	Object		v:
	 * 				String 		dom: input dom elment (path)	
	 * 				String 		id: input id	
	 * 				String 		text: input text	
	 **/
	this.input_focus = function ( v )
	{
		this.input_focus_vars[v.id] =
		{
			text: v.text,
			used: false
		};
		
		$(v.dom).focus(function(){
			if ( ! dAux.input_focus_vars[v.id].used )
				$(this).val("");
		});

		$(v.dom).blur(function(e){
			if ( $(this).val().length > 0 )
				dAux.input_focus_vars[v.id].used = true ;
			else
			{
				$(this).val(dAux.input_focus_vars[v.id].text);
				dAux.input_focus_vars[v.id].used = false ;
			}
		});

		$(v.dom).keyup(function(e){
			if ( e.which == 27 )
			{
				$(this).val("");
				dAux.input_focus_vars[v.id].used = false ;
			};
		});
		
	} ;



	//-------------------------------------
	// math functions
	//-------------------------------------

	/**
	 * floor for nagative
	 * 3.5 --> 3, -3.5 --> -3
	 * 
	 * @param	Number		n:
	 * 
	 * @return	Number		c:
	 **/
	this.floorn = function ( n )
	{
		if ( n >= 0 )
			return Math.floor ( n ) ;
		else
			return - Math.floor ( Math.abs ( n ) ) ; 
	} ;

	/**
	 * ceil for nagative
	 * 3.5 --> 4, -3.5 --> -4
	 * 
	 * @param	Number		n:
	 * 
	 * @return	Number		c:
	 **/
	this.ceiln = function ( n )
	{
		if ( n >= 0 )
			return Math.ceil ( n ) ;
		else
			return - Math.ceil ( Math.abs ( n ) ) ; 
	} ;



	/**
	 * Modulus (whit support negative values)
	 *
	 * @param	Number		r: remainder
	 * @param	Number		d: divided ( > 0 )
	 * 
	 * @return	number		m: modulus	
	 **/
	this.mod = function ( r, d )
	{
		var m ;
		
		if ( r >= 0 )
			m = r % d ;
		else
			m =  d - 1 - ( Math.abs ( r ) - 1 ) % d ;
		
		return m ;
	} ;


	/**
	 * Modulo operation (extended)
	 *
	 * @param	Number		a:
	 * @param	Number		b:
	 * @return	Array		out: 
	 * 				Number		0: out[0] * b + out[1] = a
	 * 				Number		1:
	 * 				Number		2: sign
	 */
 	this.mod_dev = function ( a, b )
	{
		var t = 0 ;
		var sign = 1 ;
		if ( a < 0 )
		{
			a = -a ;
			sign = -1 ;	
		}
		if ( a >= b )
			t = this.floorn ( a / b ) ;
		return [ t, a - t * b, sign ] ;
	} ;


	/**
	 * number (float) split into fractional and integer part
	 *
	 * @param	Number		num: number
	 * @return	Array
	 * 				Number		0: integer
	 * 				Number		1: fractional
	 **/
	this.float_split = function ( num )
	{
		var int_var = dAux.floorn ( num ) ;
		return [ int_var, num - int_var ] ;
	};


	/**
	 * round of number with specified accuracy
	 *
	 * @param	Number		n: number
	 * @param	Number		a: accuracy ( a >= 1)
	 * @return	Number		r:
	 **/
	this.roundn = function ( n, a )
	{
		var pow = Math.pow ( 10, a ) ;
		return Math.round ( n * pow ) / pow ; 
	};



	
	/**
	 * formating of number
	 *
	 * @param	Number		n: number
	 * @return	String		s:
	 **/
	this.number_format = function ( n )
	{
		var s = "" ;
		var sign = "" ;
		if ( n < 0 )
		{
			n = - n ;
			sign = "-" ;
		};
 		n = String ( n ) ;
		if ( n.length > 3 )
		{
			var r = Math.floor ( n.length / 3 ) ;
			var temp = "" ;
			for ( var i=0; i < r; i++ )
			{
				temp = n.substrn(-3,3);
				n = n.substrn(0,-3) ;
				s = s + "." + temp ;
			} ;
			s = n + s ;		
		}
		else
			s = n ;
		
		return sign + s ;
	};


	//math
	// ring_class
	// rings operations
	

	
	/**
	 * class Rings 
	 *
	 * @param	Object		param:
	 * 				Number		rang:
	 **/
	this.Rings = function ( param )
	{
		this.rang = param.rang ;
		
		this.shift = function ( a, shift )
		{
			return this.norm ( a + shift) ;
		};
		
		this.norm = function ( a )
		{
			if ( a >= this.rang || a < 0 )
				a += a > 0 ?
					- this.rang * Math.floor ( a / this.rang ) :  
					this.rang * ( 1 + ( Math.floor ( ( -a -1 ) / this.rang ) ) ) ;
			return a ;	
		};
	} ;



	//-------------------------------------
	// java script extensions
	//-------------------------------------

	//String

	/**
	 * left zerro  
	 *
	 * @param	Object		obj:
	 * 
	 * @return	Object		clone: clone of object	
	 **/
	this.lz = function ( num, count )
	{
		num = num.toString() ;
		return "0".repeat ( count - num.length ) + num ;
	};
	
	
	//Object
	
	/**
	 * object merge 
	 *
	 * @param	Object		a:
	 * @param	Object		b:
	 * 
	 * @return	Object		c:
	 **/
	this.obj_merge = function ( a, b )
	{
		var c = new Object ;
		var k ;
		for ( k in a )
			c[k] = a[k] ;
		for ( k in b )
			c[k] = b[k] ;
		return c ;
	};
	
	/**
	 * clone Object with one level  
	 *
	 * @param	Object		obj:
	 * 
	 * @return	Object		clone: clone of object	
	 **/
	this.clone_obj_one = function ( obj )
	{
		var newObj = new Object();
		for ( var i in obj )
			newObj[i] = obj[i] ;
		return newObj;
	};
	

	/**
	 * clone Object with multiple level 
	 *
	 * @param	Object		obj:
	 * 
	 * @return	Object		clone: clone of object	
	 **/
	this.clone_obj = function ( obj )
	{
		if ( typeof( obj ) != 'object' ) return obj ;
		if ( obj == null) return obj ;
		var newObj = new Object();
		for ( var i in obj )
			newObj[i] = this.clone_obj ( obj[i] ) ;
		return newObj;
	};



	//Array

	/**
	 * search ich Array 
	 *
	 * @param	Array		array:
	 * @param	Object		needle:
	 * 
	 * @return	Number		key: or false if not found	
	 **/
	this.array_search = function ( array, needle )
	{
		for ( var key in array )
			if ( needle == array [ key ] )
				return key ;
		return false ;	
	};


	this.disableSelection = function ( target )
	{
		if ( typeof target.onselectstart != "undefined" ) //IE route
			target.onselectstart = function() { return false ; }
		else if ( typeof target.style.MozUserSelect != "undefined" ) //Firefox route
			target.style.MozUserSelect = "none" ;
		else //All other route (ie: Opera)
			target.onmousedown = function() { return false } ;
		if ( typeof target.style.KhtmlUserSelect != "undefined" )
			target.style.KhtmlUserSelect = "none" ;
		target.unselectable = "on";
	}

	this.enableSelection = function ( target )
	{
		if ( typeof target.onselectstart != "undefined" ) //IE route
			target.onselectstart = {}
		else if ( typeof target.style.MozUserSelect != "undefined" ) //Firefox route
			target.style.MozUserSelect = "" ;
		else //All other route (ie: Opera)
			target.onmousedown = {} ;

		if ( typeof target.style.KhtmlUserSelect != "undefined" )
			target.style.KhtmlUserSelect = "" ;
		target.unselectable = "off";
	}
	

};

dAux = new dAux ;




	//-------------------------------------
	// string prototypes
	//-------------------------------------

String.prototype.substrn = function ( a, b )
{
	var out = "" ;
	if ( b < 0 )
	{
		out = this.substr ( a ) ;
		out = out.substr ( 0, out.length + b ) ;
	}
	else if ( b === undefined )
	{
		if ( a > 0 )
			out = this.substr ( a, this.length ) ;
		else
			out = this.substr ( 0, this.length + a ) ;
	}
	else
		out = this.substr ( a, b ) ;
	return out ;
};


/**
 * split string of numbers by "_"  
 *
 * @param	String		str: ({number}_)
 * 					
 * 
 * @return	Array		out:
 **/
String.prototype.num_split = function ()
{
	var out = this.split ( "_" ) ;
	for ( var i in out )
		out[i] = Number ( out[i] ) ;
	return out ;
};


String.prototype.repeat = function ( s )
{
	return new Array ( s + 1 ) . join ( this ) ;
};

