var _;
var isIE = document.attachEvent != null;
var isGecko = !document.attachEvent && document.addEventListener;
var isOpera = navigator.appName.toLowerCase() == 'opera';


var RegExpLibrary = {
	'default': /./gi
}


Object.prototype.extend = function(base) {
	for (var q in base) {
    	this[q] = base[q];
    }
	return this;
}


Array.prototype.each = function(f) {
	for (var q = 0, length = this.length; q < length; q++) {
		Array.prototype._ = f;
		this._(q);
	}
}
Array.prototype.del = function(item) {
	var pos = this.indexOf(item);
	if (pos != -1) this.splice(pos, 1);	
	return this;
}
if (!Array.prototype.indexOf) {
	Array.prototype.indexOf = function(item/*, from*/) {
		var length = this.length;
		var from = parseInt(arguments[1]) || 0;
		if (from < 0) from += length;	
		for (; from < length; from++) {
			if (from in this && this[from] === item) return from;
		}
		return -1;
	}
}
Array.prototype.indexOfForStr = function(item) {
	if (item == '') return -1;
	var str = this.join('__xxx__');
	var regExp = new RegExp(item, 'ig');
	var separ = new RegExp('__xxx__', 'ig');
	var pos = str.search(regExp);
	if (pos > 0) {
		str = str.slice(0, pos);
		return (isGecko) ? str.split(separ).length - 1 : str.split(separ).length;
	} else if (pos == 0) return 0;
	return -1;
}


Date.prototype.format = function(f, leng) {
	if (!this.valueOf()) return '';
	leng = leng || 'en';
	var _ = this;
	return f.replace(/(yyyy|yy|MMMM|MMM|MM|M|dddd|ddd|dd|d|HH|H|hh|h|mm|m|ss|n|tt|t)/g,
		function($1) {
			switch ($1) {
			case 'yyyy': return _.getFullYear();
			case 'yy':   return _.getFullYear().toAmplify(2);
			case 'MMMM': return Date.monthes[leng][_.getMonth()];
			case 'MMM':  return Date.monthes[leng][_.getMonth()].substr(0, 3);
			case 'MM':   return (_.getMonth() + 1).toAmplify(2);
			case 'M':    return (_.getMonth() + 1);
			case 'dddd': return Date.days[leng][_.getDay()];
			case 'ddd':  return Date.days[leng][_.getDay()].substr(0, 3);
			case 'dd':   return _.getDate().toAmplify(2);
			case 'd':    return _.getDate();
			case 'HH':   return _.getHours();
			case 'hh':   return ((h = _.getHours() % 12) ? h : 12).toAmplify(2);
			case 'h':    return ((h = _.getHours() % 12) ? h : 12);
			case 'mm':   return _.getMinutes().toAmplify(2);
			case 'm':    return _.getMinutes();
			case 'ss':   return _.getSeconds().toAmplify(2);
			case 's':    return _.getSeconds();
			case 'tt':   return _.getHours() < 12 ? 'AM' : 'PM';
			case 't':    return _.getHours() < 12 ? 'a' : 'p';
			}
		}
	);
}

Date.days = {};
Date.days['en'] = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];

Date.monthes = {};
Date.monthes['en'] = ['January','February','March','April','May','June','July','August','September','October','November','December'];


Number.prototype.toAmplify = function(n) {
	var _ = '';
	var str = this.toString();
	var x = n - str.length;
	if (x > 0) for (var q = 0; q < x; q++) _ += '0';
	else if (x < 0) str = str.slice(x*-1);
	return _ + str;
}
Number.prototype.format = function(f) {
	if (!this.valueOf()) return '';
	var _ = this;
	var sign = (this < 0) ? -1 : 1;
	var a = Math.floor(Math.abs(_)) * sign;
	
	var b = f.indexOf('b');
	if (b != -1) {
		var qB = f.slice(b-1, b)*1;
		var zero = (f.charAt(b+1) == '0') ? true : false;
		if (zero) f = f.slice(0, b+1) + f.slice(b+2);
		if (qB) f = f.slice(0, b-1) + f.slice(b);
		b = (_+'').indexOf('.');
		b = (b != -1) ? (_+'').slice(b+1)*1 : 0;
		if (qB) {
			b = (b+'').slice(0, qB);
			while (zero && (qB > b.length)) b += '0';
		}
	} else b = 0;
	f = f.replace(/(a|b)/g,
		function($1) {
			switch ($1) {
			case 'a':    return a;
			case 'b':    return b;
			}
		}
	);
	return f;
}
//alert((78234847.123465).format('$ a,2b0 руб.'));


Boolean.prototype.format = function(f) {
	if (this == true) return f.substring(0, f.indexOf('#'));
	else return f.substr(f.indexOf('#')+1);
}


String.prototype.format = function(f) {
	return this;
}


var Format = function() {
	if (Format.arguments.length == 0) return;
	
	var pattern = /(\{\d+:*[^\}]*\})/gi;
	var f = Format.arguments[0];

	for (var q = 1, l = Format.arguments.length, variables = []; q < l; q++) variables.push(Format.arguments[q]);

	var items = f.match(pattern);
	for (var q = 0, l = items.length, N, selfFormat; q < l; q++) {
		N = items[q].substring(1, items[q].search(/[:\}]/))*1;
		selfFormat = (items[q].indexOf(':') != -1) ? items[q].substring(items[q].indexOf(':')+1, items[q].length-1) : null;
		items[q] = variables[N].format(selfFormat);
	}
	
	var a = 0;
	return f.replace(pattern, function($1) {var _ = items[a]; a++; return _});
}


var isArray = function (variable) {return ((typeof variable == 'object') && (variable.constructor == Array));}
var isStr = function(variable) {return ((typeof variable == 'string') && (variable.constructor == String));}
var isUndef = function(variable) {return ((typeof variable == 'undefined') ? true : false)}


var Event = {
	attach: function(elem, e, action, propagation) {
		elem = elem || document;
		if (isIE) elem.attachEvent('on'+e, action);
		if (isGecko) elem.addEventListener(e, action, propagation);
	},
	detach: function(elem, e, action, propagation) {
		elem = elem || document;
		if (isIE) elem.detachEvent('on'+e, action);
		if (isGecko) elem.removeEventListener(e, action, propagation);
	},
	return_: function() {return event}
}


/* RUN----------------------------------------------------*/
var Run = {
	start: function(func, delay, speed) {
		delay = delay || this.delay;
		speed = speed || this.speed;
		this._ = {timer: false, interval: false};
		if (!this._.timer) {
			var rand = Math.random() + '';
			this.timer[rand] = this._;
			this._.timer = setTimeout(function() {Run._.interval = setInterval(func, speed)}, delay);
			return rand;
		} else return false;
	},
	stop: function(timer) {
		_timer = this.timer[timer];
		clearTimeout(_timer.timer);
		if (_timer.interval) clearInterval(_timer.interval);
		timer = false;
		return timer;
	},
	delay: 500,
	speed: 50,
	timer: {}
}


/* GET ELEMENTS -------------------------------------------*/
var GetElement = {
	byParam: function(param, value, elem) {
		elem = elem || document;
		elem.childs = elem.all || elem.getElementsByTagName('*');
		for (var q = 0, length = elem.childs.length; q < length; q++) {
			if (elem.childs[q].getAttribute(param) && elem.childs[q].getAttribute(param) == value) return elem.childs[q];
		}
		return null;
	}
}


var Geom = {
	getSize: function(element) {
		return {width: element.offsetWidth, height: element.offsetHeight}
	},
	getCoords: function(element) {
		var parent = element.offsetParent;
		var _ = $(element).offset();
		var coords = {x: _.left, y: _.top};
//		alert(_.left);
//		while (element != parent)	{
//			coords.x += element.offsetLeft;
//			coords.y += element.offsetTop;
//			element = element.offsetParent;
//		}
		return coords;
	}
}

var Compare = {
	'integer': function(a, b) {
		return parseInt(a) - parseInt(b);
	},
	'float': function(a, b) {
		return parseFloat(a) - parseFloat(b);
	},
	'numeric': function(a, b) {
		return parseFloat(a) - parseFloat(b);
	},
	'string': function(a, b) {
		a = a.toLowerCase();
		b = b.toLowerCase();
		return (a == b) ? 0 : (a > b) ? 1 : -1;
	},
	'date': function(a, b) {
		a = (!isNaN(new Date(a))) ? new Date(a) : new Date(a*1);
		b = (!isNaN(new Date(b))) ? new Date(b) : new Date(b*1);
		return (!isNaN(a) && !isNaN(b)) ? a-b : 0;
	},
	'boolean': function(a, b) {
		a = eval(a);
		b = eval(b);
		return (a == b) ? 0 : (a > b) ? 1 : -1;
	}
}


var BaseClass = {
	'init': function(item) {
		item.extend = this.extend;
		item.extend(this);
		item.DOM();
		item.isInit = true;
		return item;
	},

	'DOM': function() {

	}
}


var ClassName = {
    test: function(elem, name) {
        if(!elem) return false;
        if(!name) return true;
        return this._rName(name).test(elem.className);
    },
    set: function(elem, name) {
        if(!elem) return;
        if(elem.className != name) elem.className = name;
    },
    add: function(elem, name) {
        if (!elem) return;
        if (!this.test(elem, name)) elem.className += ' ' + name;
    },
    remove: function(elem, name) {
        if (!elem) return;
        if (this.test(elem, name)) elem.className = normalizeSpace(elem.className.replace(this._rName(name), '$1$2'));
    },
    assign: function(elem, name, test) {
        if (!elem) return;
        if (test) this.add(elem, name);
        else this.remove(elem, name);
    },
    replace: function(elem, find, replace) {
        if (!elem) return;
        if (this.test(elem, find)) elem.className = elem.className.replace(this._rName(find), '$1'+replace+'$2');
    },
    swap: function(elem, one, two) {
        if (!elem) return;
        if (this.test(elem, one)) this.replace(elem, one, two);
        else if (this.test(elem, two)) this.replace(elem, two, one);
        else this.add(elem, one);
    },
    _rName: function(name) {
        return new RegExp('(^|\\s+)'+escapeRegexp(name)+'(\\s+|$)','');
    }
};
function escapeRegexp(text) {
	return text.replace(/([\|\!\[\]\^\$\(\)\{\}\+\=\?\.\*\\])/g,"\\$1");
}
function normalizeSpace(str) {
	return trim(str.replace(/[\s\xA0]{2,}/g,' '));
}
function trim(str) {
	return str.replace(/^[\s\xA0]+/,'').replace(/[\s\xA0]+$/,'');
}





var Change = {
	'width': function(item, finalDestination, speed, stopping, postAction) {
		this.item = item;
		stopping = (stopping) ? true : false;
		item.changeWidthObj = this._createParams(finalDestination, speed, stopping, postAction);
		if (item.isChangingWidth) {
			clearInterval(item._chW);
			item.isChangingWidth = false;
		}
		item.isChangingWidth = false;
		item._chW = setInterval(function() {Change._width(item)}, 1);
	},
	'height': function(item, finalDestination, speed, stopping, postAction) {
		this.item = item;
		stopping = (stopping) ? true : false;
		item.changeHeightObj = this._createParams(finalDestination, speed, stopping, postAction);
		if (item.isChangingHeight) {
			clearInterval(item._chH);
			item.isChangingHeight = false;
		}
		item.isChangingHeight = false;
		item._chH = setInterval(function() {Change._height(item)}, 1);
	},
	'x': function(item, finalDestination, speed, stopping, postAction) {
		this.item = item;
		stopping = (stopping) ? true : false;
		item.changeXObj = this._createParams(finalDestination, speed, stopping, postAction);
		if (item.isChangingX) {
			clearInterval(item._chX);
			item.isChangingX = false;
		}
		item.isChangingX = false;
		item._chX = setInterval(function() {Change._x(item)}, 1);
	},
	'y': function(item, finalDestination, speed, stopping, postAction) {
		this.item = item;
		stopping = (stopping) ? true : false;
		item.changeYObj = this._createParams(finalDestination, speed, stopping, postAction);
		if (item.isChangingY) {
			clearInterval(item._chY);
			item.isChangingY = false;
		}
		item.isChangingY = false;
		item._chY = setInterval(function() {Change._y(item)}, 1);
	},

	_width: function(item, finalDestination, speed, stopping, postAction) {
		item.isChangingWidth = true;
		var params = item.changeWidthObj;
		var _ = parseInt(item.style.width) || null;
		_ = this._do(item, _, params.finalDestination, params.speed, params.postAction);
		if (_) item.style.width = _ + "px";
		else if (params.stopping) {
			clearInterval(item._chW);
			item.isChangingWidth = false;
		}
	},
	_height: function(item, finalDestination, speed, stopping, postAction) {
		item.isChangingWidth = true;
		var params = item.changeHeightObj;
		var _ = parseInt(item.style.height) || null;
		_ = this._do(item, _, params.finalDestination, params.speed, params.postAction);
		if (_) item.style.height = _ + "px";
		else if (params.stopping) {
			clearInterval(item._chH);
			item.isChangingHeight = false;
		}
	},	
	_x: function(item, finalDestination, speed, stopping, postAction) {
		item.isChangingWidth = true;
		var params = item.changeXObj;
		var _ = parseInt(item.style.left) || null;
		_ = this._do(item, _, params.finalDestination, params.speed, params.postAction);
		if (_) item.style.left = _ + "px";
		else if (params.stopping) {
			clearInterval(item._chX);
			item.isChangingX = false;
		}
	},
	_y: function(item, finalDestination, speed, stopping, postAction) {
		item.isChangingWidth = true;
		var params = item.changeYObj;
		var _ = parseInt(item.style.top) || null;
		_ = this._do(item, _, params.finalDestination, params.speed, params.postAction);
		if (_) item.style.top = _ + "px";
		else if (params.stopping) {
			clearInterval(item._chY);
			item.isChangingY = false;
		}
	},
	
	_do: function(item, param, finalDestination, speed, postAction) {
		document.title = document.title;
		if (finalDestination.constructor == Function) finalDestination = finalDestination();
		speed = speed || .1;
		var D;
		if (finalDestination != param) {
			D = speed * (finalDestination - param);
			D = (D > 0) ? Math.ceil(D) : Math.floor(D);
			param += D;
			return param;
		} else {
			if (postAction) {postAction();}
			return null;
		}
	},
	_createParams: function(finalDestination, speed, stopping, postAction) {
		return {finalDestination: finalDestination, speed: speed, stopping: stopping, postAction: postAction}
	}
}
