var isnull = function(x){
	return (typeof x == null || typeof x == 'undefined');
}

var isnumber = function(x){
	return (typeof x == 'number');
}

var isstring = function(x){
	return (typeof x == 'string');
}

var addlistener = function(x, e, f){
	if (x.addEventListener) {
		x.addEventListener (e, f, false);
	} else if (x.attachEvent) {
		x.attachEvent ('on' + e, f); 
	};
}

var removelistener = function(x, e, f){
	if (x.removeEventListener) {
		x.removeEventListener (e, f, false);
	} else if (x.detachEvent) {
		x.detachEvent ('on' + e, f); 
	};
}

var Convert = new NameSpace({
	tonumber : function(x){
		switch (typeof x){
			default:
				return 0;
			break;
			case 'string':
				var d = '0123456789';
				var n = '';
				
				for (var i = 0; i < x.length; i++){
					if (d.indexof(x[i]) >= 0 || (x[i] == '-' && i == 0)){
						n += x[i];
					}
				}
				
				if (n == ''){
					n = '0';
				}
				
				return Number(n);
			break;
			case 'boolean':
				return (x ? 1 : 0);
			break;
			case 'number':
				return x;
			break;
		}
	},
	
	tostring : function(x){
		switch (typeof x){
			default:
				return '';
			break;
			case 'number':
				return String(x);
			break;
			case 'boolean':
				return (x ? 'true' : 'false');
			break;
			case 'string':
				return x;
			break;
		}
	},
	
	toboolean : function(x){
		switch (typeof x){
			default:
				return false;
			break;
			case 'string':
				return (x == 'true');
			break;
			case 'number':
				return (x > 0);
			break;
			case 'boolean':
				return x;
			break;
		}
	}
});

var Events = new NameSpace({
	load : 'load',
	
	click : 'click',
	
	mouseover : 'mouseover',
	
	mousemove : 'mousemove',
	
	mousedown : 'mousedown',
	
	mouseup : 'mouseup',
	
	keydown : 'keydown',
	
	keyup : 'keyup',
	
	keypress : 'keypress',
	
	change : 'change'
});

var Event = new Class({
	_initialize : function(p){
		if (p){ this.extend(p); }
	},
	
	_type: 'event'
});

var Collection = new Class({
	_initialize : function(p){
		if (p){
			this.extend(p);
		}
		
		return new Array();
	},
	
	_type : 'collection',
	
	types : [],
	
	indexes : [],
	
	repeat : false,
	
	add : function(x){
		if ((_indexof(this.types, '*') >= 0 || _indexof(this.types, _typeof(x)) >= 0) && ((this.repeat) || (!this.repeat && this.indexof(x) < 0))){
			this.push(x);
			
			if (this._owner){
				if (this.onadd){
					this.onadd.apply(this._owner, [x]);
				}
				
				if (this.onlengthchanged){
					this.onlengthchanged.apply(this._owner);
				}
			}else{
				if (this.onadd){
					this.onadd(x);
				}
				
				if (this.onlengthchanged){
					this.onlengthchanged();
				}
			}
			
			return x;
		}
	},
	
	addrange: function(x){
		for (var i = 0; i < x.length; i++){
			this.add(x[i]);
		}
	},
	
	get : function(v){
		for (var i = 0; i < this.length; i++){
			for (var j = 0; j < this.indexes.length; j++){
				if (this[i][this.indexes[j]] == v){
					return this[i];
				}
			}
		}
	},
	
	getall : function(v){
		var r = [];
		
		for (var i = 0; i < this.length; i++){
			for (var j = 0; j < this.indexes.length; j++){
				if (this[i][this.indexes[j]] == v){
					r.push(this[i]);
					continue;
				}
			}
		}
		
		return r;
	},
	
	find : function(p){
		var isok = true;
		for (var i = 0; i < this.length; i++){
			isok = true;
			for (var a in p){
				if (this[i][a] != p[a]){					
					isok = false;
					break;
				}
			}
			
			if (isok){ return this[i]; }
		}
	},
	
	findall : function(p){
		var r = [];
		var isok = true;
		for (var i = 0; i < this.length; i++){
			isok = true;
			for (var a in p){
				if (this[i][a] != p[a]){
					isok = false;
					break;
				}
			}
			
			if (isok){ r.push(this[i]); }
		}
		
		return r;
	},
	
	indexof : function(x){
		return _indexof(this, x);
	},
	
	contains : function(x){
		return _indexof(this, x) >= 0;
	},
	
	remove : function(x){
		if (this.indexof(x) >= 0){
			if (this.onremove){
				this.onremove(x);
			}
			
			this.splice(this.indexof(x), 1);
			
			if (this.onlengthchanged){
				this.onlengthchanged();
			}
		}
	},
	
	clear : function(){
		while (this.length > 0){
			this.remove(this[0]);
		}
	}
});

var Point = new Class({
	_initialize: function(p){
		if (p){ this.extend(p); }
		
		this.extend({
			_observer: new Observer({
				autostart: true,
				properties: {x: null, y: null},
				actions: {
					x: function(){ if (this._owner){ this._owner.style.left = this.x + 'px'; } },
					y: function(){ if (this._owner){ this._owner.style.top = this.y + 'px'; } }
				}
			})
		});
	},
	
	_type : 'point',
	
	x : 0,
	
	y : 0
});

var Size = new Class({
	_initialize: function(p){
		if (p){ this.extend(p); }
		
		this.extend({
			_observer: new Observer({
				autostart: true,
				properties: {width: null, height: null},
				actions: {
					width: function(){ if (this._owner){ this._owner.style.width = this.width + 'px'; } },
					height: function(){ if (this._owner){ this._owner.style.height = this.height + 'px'; } }
				}
			})
		});
	},
	
	_type : 'size',
	
	width : 0,
	
	height : 0
});

var Rectangle = new Class({
	_initialize: function(p){
		if (p){ this.extend(p); }
		
		this.extend({
			_observer: new Observer({
				autostart: true,
				properties: {x: null, y: null, width: null, height: null},
				actions: {
					x: function(){ if (this._owner){ this._owner.style.left = this.x + 'px'; } },
					y: function(){ if (this._owner){ this._owner.style.top = this.y + 'px'; } },
					width: function(){ if (this._owner){ this._owner.style.width = this.width + 'px'; } },
					height: function(){ if (this._owner){ this._owner.style.height = this.height + 'px'; } }
				}
			})
		});
	},
	
	_type : 'rectangle',
	
	x : 0,
	
	y: 0,
	
	width : 0,
	
	height : 0
});

var Observer = new Class({
	_initialize : function(p){
		if (p){ this.extend(p); }
		
		if (this.properties){ delete this.properties._owner; }		
		if (this.autostart){ this.start(); }
	},
	
	_type : 'observer',
	
	_intervalid : -1,
	
	autostart : false,
	
	properties : {},
	
	protection : {},
	
	actions : {},
	
	_apply : function(){
		if (this._owner && this.properties && this.actions){
			for (var p in this.properties){
				if (this._owner[p] != this.properties[p]){
					if (this.protection[p] && this.properties[p]){
						this._owner[p] = this.properties[p];
					} else {
						this.properties[p] = this._owner[p];
						
						if (this.actions[p]){ this.actions[p].apply(this._owner, [this.properties[p]]); }
					}
				}
			}
		}
	},
	
	start : function(){
		var x = this;
		var f = function(){
			x._apply();
		}
		
		this._intervalid = setInterval(f, 1);
	},
	
	stop : function(){
		clearInterval(this._intervalid);
		this._intervalid = -1;
	},
	
	breakonce : function(x){
		for (var p in x){
			if (this.protection[p]){ this.properties[p] = x[p]; }
		}
	}
});
