function $(elem) { return document.getElementById(elem); }
function $N(elem) { return document.getElementsByName(elem)[0]; }
function $NL(elem) { return document.getElementsByName(elem); }

function Dump(arr, level) {
	var dumped_text = "";
	if (!level) level = 0;

	var level_padding = "";
	for (var j=0;j<level+1;j++) level_padding += "    ";

	if (typeof(arr) == 'object') { //Array/Hashes/Objects
		for(var item in arr) {
	  var value = arr[item];
	 
	  if(typeof(value) == 'object') { //If it is an array,
	  	dumped_text += level_padding + "'" + item + "' ...\n";
			dumped_text += Dump(value,level+1);
	  } else {
	  	dumped_text += level_padding + "'" + item + "' => \"" + value + "\"\n";
	  }
	 }
	} else { //Stings/Chars/Numbers etc.
		dumped_text = "===>"+arr+"<===("+typeof(arr)+")";
	}
	return dumped_text;
} 

var Utils = {};

Utils.A = function() {
	return {
		removeByKey: function(key, A) {
			var i, B = [];
			for (i=0; i<A.length; i++) if (i != key) B[B.length] = A[i];
			
			return B;
		},
		
		removeByValue: function(value, A) {
			var i, B = [];
			for (i=0; i<A.length; i++) if (A[i] != value) B[B.length] = A[i];
			
			return B;
		}
		
	}
}();

Utils.Common = function() {
  return {
    set_home: function(obj) {
    	if (Utils.Navigator.IE()) {  
    		obj.style.behavior = 'url(#default#homepage)'; 
    		obj.setHomePage(document.location);
    	}
    	else {
    		alert('Эта функция доступна в Internet Explorer.');
    	}
    	return false;
    },

    add_favorite: function(title) {
    	if (Utils.Navigator.IE()) {
    		window.external.addFavorite('http://'+ location.hostname +'/', title); 
    	}
    	else {
    		alert('Эта функция доступна в Internet Explorer, используйте CTRL-D');
    	}
    	return false;
    },
		
		toggle: function(elem, show) {
    	if (typeof elem == 'string') elem = $(elem);
    	if (show != undefined && show != null) elem.style.display = (show) ? 'block': 'none';
    	else elem.style.display = (elem.style.display == 'block') ? 'none': 'block';
    },
    
    absolute_position: function(elem) {
    	var T = 0, L = 0, res = {top: 0, left: 0};  
    	var obj = (elem.tagName)? elem: $(elem);  
    	while(obj) {
  	    L += obj.offsetLeft;
  	    T += obj.offsetTop;
  	    obj = obj.offsetParent;
    	}
  
    	return {top: T, left: L};
    },
    
    radio_value: function(name) {
    	var list = $NL(name);
    	
    	for (var i=0; i<list.length; i++) 
    		if (list[i].tagName == 'INPUT' && list[i].type == 'radio' && list[i].checked) return list[i].value;
    }
    
  }
}();

Utils.Measure = function() {
	return  {
		windowHeight: function() {
			var de = document.documentElement;
			return self.innerHeight || ( de && de.clientHeight ) || document.body.clientHeight;
		},
		
		windowWidth: function() {
			var de = document.documentElement;
			return self.innerWidth || ( de && de.clientWidth ) || document.body.clientWidth;
		},
		
		scrollTop: function() {
			var de = document.documentElement;
			return ( de && de.scrollTop ) || document.body.scrollTop;
		},
		
		contentWidth: function() {
			var d = document, b = d.body, e = d.documentElement;
			return Math.max(Math.max(b.scrollWidth, e.scrollWidth), Math.max(b.clientWidth, e.clientWidth))
		},
		 
		contentHeight: function() {
			var d = document, b = d.body, e = d.documentElement;
			return Math.max(Math.max(b.scrollHeight, e.scrollHeight), Math.max(b.clientHeight, e.clientHeight));
		}
	}
}();

Utils.Special = function() { return {

	utf8_encode: function(string) {
		string = string.replace(/\r\n/g,"\n");
		var utftext = "";
 
		for (var n = 0; n < string.length; n++) {
			var c = string.charCodeAt(n);
			if (c < 128) {
				utftext += String.fromCharCode(c);
			}
			else if((c > 127) && (c < 2048)) {
				utftext += String.fromCharCode((c >> 6) | 192); utftext += String.fromCharCode((c & 63) | 128);
			}
			else {
				utftext += String.fromCharCode((c >> 12) | 224); 
				utftext += String.fromCharCode(((c >> 6) & 63) | 128);
				utftext += String.fromCharCode((c & 63) | 128);
			}
		}
		return utftext;
	},
	
	crc32: function(str) {
		var x = 0, i = 0, crc = 0;
    for(i=0; i<str.length; i++) {
      x = str.charCodeAt(i);
      crc  = (x << i) >> 12;
    }
    return crc;
	}

}}();

Utils.Navigator = function() {
  return {
    IE:     function() { return (navigator.userAgent.indexOf("MSIE") != -1); },
    Opera:  function() { return (navigator.userAgent.indexOf("Opera") != -1); },
    FF:     function() { return (navigator.userAgent.indexOf("Firefox") != -1 || navigator.userAgent.indexOf("Chrome") != -1); }  
  }
}();

Utils.Date = function() {
	return {
		parse: function(value, format) {
			var A = [], d = 0, m = 0, y = 0;
			A = value.split('-');
			d = A[0];
			m = A[1];
			y = A[2];
			
			return Date.parse(m + '/' + d + '/' + y);
		}
	}
}();

Utils.Init = function() {
  var _InitiateComplete = false;
  var _TimerHandle = null;
  var _Path = '';
  
  var _OnLoadStack = Array();

  return {
  	
  	JSPath: '',
  	InjectedScripts: new Array(),
    
    _get_requires: function() {
      var list = document.getElementsByTagName("script");
      for (var i=0; i<list.length; i++) {
        var m = list[i].src.match(/utils\.js\?load=(.*)/i);
        if (m) break;
      }
      
      if (list[i]) {
	      this.JSPath = _Path = list[i].src.replace(/utils\.js\?load=(.*)/i, '');
	      return m[1].split(',');
      }
    },
    
    load_requires: function() {
      var scripts = Utils.Init._get_requires();
      if (!scripts) return;
      
      var list = document.getElementsByTagName("script");
      var already_included = Array();
      for (var i=0; i<list.length; i++) {
        var m = list[i].src.match(/utils\.(.+)\.js/i);
        if (m) already_included.push(m[1]);
      }
      
      for (var i=0; i<scripts.length; i++) {
        var src = _Path + 'utils.' + scripts[i] + '.js';
        var included = false;
        
        for (var j=0; j<already_included.length; j++) if (already_included[j] == scripts[i]) included = true;
        if (!included) Utils.Init.load_script(src);
      }
    },
    
    extract_scripts: function(content) {
			var js_code = '';
			
			var gmatch = content.match(/<script[^>]*>([\u0001-\uFFFF]*?)<\/script>/ig);
			if (gmatch) {
				var match = null;
				var value = '';
				for (var i=0; i<gmatch.length; i++) {
					value = gmatch[i];
					match = value.match(/<script[^>]*>([\u0001-\uFFFF]*?)<\/script>/i);
					if (match) js_code += match[1];
				}
			}
			return js_code;
		},
		
		load_script: function(src) {
			var script = document.createElement('script');
			script.setAttribute('type', 'text/javascript');
			script.setAttribute('src', src);
			// InsertBefore for IE.
			// IE crashes on using appendChild before the head tag has been closed.
			var head = document.getElementsByTagName('head').item(0);
			head.insertBefore(script, head.firstChild);
		},
		
		load_style: function(src) {
      var ref = document.createElement("link");
      ref.setAttribute("rel", "stylesheet");
      ref.setAttribute("type", "text/css");
      ref.setAttribute("href", src);
      
      if (typeof ref != "undefined") document.getElementsByTagName("head")[0].appendChild(ref);
    },
		
		inject_script: function(js_code) {
			if (!js_code) return false;
			
			js_crc = Utils.Special.crc32(js_code);
			for (var i=0; i<this.InjectedScripts.length; i++) if (this.InjectedScripts[i] == js_crc) return false;
			
			this.InjectedScripts.push(js_crc);
			
			if (Utils.Navigator.IE()) {
				window.execScript(js_code);
			} 
			else {
				var script = document.createElement('script');
				script.innerHTML = js_code;
				document.getElementsByTagName('head')[0].appendChild(script);
			}
		},
    
    observe: function(func) {
    	if (!_InitiateComplete) _OnLoadStack.push(func);
    	else if (typeof func == 'function') func();
    },
    
    initiate: function() {
      // Load requires
      Utils.Init.load_requires();
    
      // Values
    	Utils.Init.initiate_values();
    	
    	_InitiateComplete = true;
    	
    	for (var i=0; i<_OnLoadStack.length; i++) { if (typeof _OnLoadStack[i] == 'function') _OnLoadStack[i](); }
    },
    
    initiate_values: function() {
    	Utils.Init.init_input_hints();
    	Utils.Init.init_select_values();
    	Utils.Init.init_checkbox_values();
    	Utils.Init.init_radio_values();
    },
    
    init_input_hints: function() {
    	for (var i=0; i<document.getElementsByTagName('input').length; i++) {
    		var elem = document.getElementsByTagName('input')[i];
    		if (elem.getAttribute('initiated') == 'true') continue;
    		
    		if (elem.getAttribute('default') == 'true') {
    			elem.focus();
    			elem.setAttribute('initiated', 'true');
    		}
    		
    		var hint = elem.getAttribute('hint');
    		if (hint) {
    			elem.value = !elem.value ? hint : elem.value;
    			elem.onfocus = Utils.Init.hint_focus.bind(elem);
    			elem.onblur = Utils.Init.hint_blur.bind(elem);
    			elem.setAttribute('initiated', 'true');
    		}
    	}
    },
  
    hint_focus: function(elem) {
    	var hint = this.getAttribute('hint');
    	if (!this.value || this.value == hint) {
    		this.value = '';
    	}
    },
    
    hint_blur: function() {
    	var hint = this.getAttribute('hint');
    	if (!this.value) {
    		this.value = hint;
    	}
    },
  
    init_select_values: function() {
    	var list = document.getElementsByTagName('select');
    	for (var i = 0; i < list.length; i++) {
    		var elem = list[i];
    		var defaultIndex = null;
    		var selValue = elem.getAttribute('metavalue');
  			if (elem.getAttribute('initiated') == 'true') continue;
  			for (var j = 0; j< elem.options.length; j++) {
  				var option = elem.options[j];
  				if (option.getAttribute('default') == 'true') defaultIndex = j;
  				if (option.value == selValue) {
  					option.selected = true;
  					defaultIndex = null;
  					break;
  				}
  			}
  			if (defaultIndex) elem.options[defaultIndex].selected = true;
  			elem.setAttribute('initiated', 'true');
    	}
    },
    
    init_checkbox_values: function() {
    	var list = document.getElementsByTagName('input');  	
    	for (var i = 0; i < list.length; i++) {
    		var elem = list[i];
    		
    		var metaValue = elem.getAttribute('metavalue');
    		if (metaValue == 1 && elem.type == 'checkbox' && elem.getAttribute('initiated') != 'true') {
    			elem.checked = true;
    			elem.setAttribute('initiated', 'true');
    		}
    	}
    },
    
    init_radio_values: function() {
    	var list = document.getElementsByTagName('input');
    	for (var i = 0; i < list.length; i++) {
    		var elem = list[i];
    		
    		var metaValue = elem.getAttribute('metavalue');
    		if (metaValue == elem.value && elem.type == 'radio' && elem.getAttribute('initiated') != 'true') {
    			elem.checked = true;
    			elem.setAttribute('initiated', 'true');
    		}
    	}
    }
    
  }
}();

Utils.Event = function() {
  return {
    
    add: function(element, name, observer, capture) {
    	if (typeof element == 'string') element = $(element);
      
      if (element.addEventListener) element.addEventListener(name, observer, capture);
      else if (element.attachEvent) element.attachEvent('on' + name, observer);
    },
    
    remove: function(element, name, observer, capture) {
    	if (typeof element == 'string') element = $(element);
    	
      if (element.removeEventListener) element.removeEventListener(name, observer, capture);
      else if (element.detachEvent) element.detachEvent('on' + name, observer);
    }
  }
}();


var $A = function(iterable) {
  if (!iterable) return [];
  if (iterable.toArray) {
    return iterable.toArray();
  } else {
    var results = [];
    for (var i = 0, length = iterable.length; i < length; i++)
      results.push(iterable[i]);
    return results;
  }
};

Function.prototype.bind = function() {
  var __method = this, args = $A(arguments), object = args.shift();
  return function() {
    return __method.apply(object, args.concat($A(arguments)));
  }
};

/*
HTMLElement.prototype.absolute_position = function() {
	return Utils.Common.absolute_position(this);
}

HTMLElement.prototype.remove = function() {
	if (this.parentNode) this.parentNode.removeChild(this);
}
*/



Utils.Event.add(window, 'load', Utils.Init.initiate, false);
