/*	Copyright (c) by majortom.ch, St. Johannsring 51, CH-4056 Basel
*		If you are interested in this code, please send me an email info@majortom.ch
*/

mt = {
	__constructor:function(){
		
		//utilities
		mt.include.addFile({namespace:'mt.animation',file:'utils/animation.js'});
		mt.include.addFile({namespace:'mt.state',file:'utils/state.js'});

		//html
		mt.include.addFile({namespace:'mt.html',file:'html/html.js'});
		mt.include.addFile({namespace:'mt.html.element',file:'html/element.js',needs:'mt.html,mt.animation'});
		mt.include.addFile({namespace:'mt.html.div',file:'html/basic_elements.js',needs:'mt.html.element'});
		
		this.onload = new mt.Event({name:'onload',target:this});
	},
	version:'0.1 alpha',
	path_mt:'_js/_mt/'	//main path to mt framework
};



/*
| public function mt.Class
|
| generates a class from an object.
| @param {object}, Object usually in json notation
|	@return {function}, Class from which an object can be generated.
*/
mt.Class = function(_obj){
	//real constructor
	var oClass = function(_arg){
		//call constructor chain
		for(var member in this.__constructor)
			this.__constructor[member].call(this,_arg);
	};

	//create pseudo constructor array
	oClass.prototype.__constructor = new Array();	
	
	if(typeof(_obj['__super'])=='function'){
		//add pseudo constructor from _obj['__super']
		for(var member in _obj['__super'].prototype['__constructor'])
			oClass.prototype.__constructor[oClass.prototype.__constructor.length] = _obj['__super'].prototype['__constructor'][member];
	
		//add properties from _obj['__super']
		for(var member in _obj['__super'].prototype){
			if(member.substring(0,2) != '__'){
				oClass.prototype[member] = _obj['__super'].prototype[member];
			}
		}
	}
	
	//add pseudo constructor from _obj
	if(typeof(_obj['__constructor'])=='function')
		oClass.prototype.__constructor[oClass.prototype.__constructor.length] = _obj['__constructor'];
	
	//add member __super
	if(typeof(_obj['__super'])=='function')
		oClass.prototype['__super'] = _obj['__super'];	
	
	//add properties from _obj
	for(var member in _obj){
			if(member.substring(0,2) != '__'){
				oClass.prototype[member] = _obj[member];
			}
	}
	
	oClass.prototype.constructor = oClass;

	return oClass;
}



/*
| public class mt.Event
|
|	@method addListener(), calls the handler function within scope
|	@method removeListener(),
|	@method fire(), 
*/
mt.Event = mt.Class({
	__constructor:function(_arg){
		this._listener = new Array();
		this.name = (typeof _arg['name'] == 'string') ? _arg['name'] : '';	
		this.target = (typeof _arg['target'] != 'undefined') ? _arg['target'] : null;
	},

	name:'',
	target:null,

	addListener:function(_arg){
		this._listener[this._listener.length] = new mt.Event.Listener(_arg);
		return this._listener[this._listener.length-1];
	},
	removeListener:function(_listener){
		for(var i=0;i<this._listener.length;i++)
			if(this._listener[i]==_listener) this._listener.splice(i,1);
	},
	fire:function(_arg){
		for(var i=0;i<this._listener.length;i++)
			this._listener[i].callHandler(_arg);
	},

	_listener:null
});



/*
| public class mt.Event.Listener
|
| @param {function}, handler for the event
|	@param {object}, scope where the handler will be executed
|	@method callHandler(), calls the handler function within scope
|		@param {object}, 
*/
mt.Event.Listener = mt.Class({
	__constructor:function(_arg){
		this._handler = (typeof(_arg['handler'])=='function') ? _arg['handler'] : function(){};
		this._scope = (typeof(_arg['scope'])=='object') ? _arg['scope'] : this;
	},
	callHandler:function(_value){
		this._handler.call(this._scope,_value);
	},
	_handler:null,
	_scope:null
});


/*
| public class mt.include
|	@singleton
|
| @method addFile(_namespace,_file), 
|	@method use(_namespace), 
| @method setLoaded(_file)
*/
mt.include = {
	__constructor:function(){
		this.onfileloaded = new mt.Event({name:'onfileload',target:this});
		this.onfileloaded.addListener({handler:this.setLoaded,scope:this});
	},

	files:[],
	onfileload:null,
	nFile:0,

	addFile:function(_arg){
		if(typeof(_arg['file']) != 'string') return null;
		
		var register = true;
		for(var i=0;i<this.files.length;i++){
			if(this.files[i].file == _arg['file'])
				register = true;
		}

		if(register)
			this.files[this.files.length] = new mt.include.File(_arg);
	},

	use:function(_namespace){
		if(typeof(_namespace)!='string' || _namespace == '') return null;

		var re = eval('/^'+_namespace.replace(/\*/g,'[^,]*')+'$/');

		for(var i=0;i<this.files.length;i++){
			if(re.test(this.files[i].namespace)){
				//import needed files
				var needs = this.files[i].needs.split(',');
				for(var j=0;j<needs.length;j++)
					this.use(needs[j]);

				//request for import
				this.files[i].setState(1);
			}
		}
	},

	load:function(){
		var bImported = false;

		for(var i=this.nFile;i<this.files.length;i++){
			if(this.files[i].state == 1){
				this.files[i].importFile();
				this.nFile = i;
				i=this.files.length;
				bImported =true;
			}
		}
		if(!bImported) mt.onload.fire();
	},

	setLoaded:function(){
		this.files[this.nFile].setState(3);
		this.load();
	}
};

mt.include.File = mt.Class({
	__constructor:function(_arg){
		this.setFile(_arg['file']);
		this.setNamespace(_arg['namespace']);
		this.setNeeds(_arg['needs']);
		this.setState(_arg['state']);
	},

	file:'',
	namespace:'',
	needs:'',
	state:0,	//0:default, 1:request load, 2:loading, 3:loaded

	setFile:function(_value){
		if(typeof(_value)!='string') return null;
		this.file = _value;
	},
	setNamespace:function(_value){
		if(typeof(_value)!='string') return null;
		this.namespace = _value;
	},
	setNeeds:function(_value){
		if(typeof(_value)!='string') return null;
		this.needs = _value;
	},
	setState:function(_value){
		if(typeof(_value)!='number') return null;
		this.state = _value;
	},
	importFile:function(){
		if(this.state != 1) return null;
		
		this.state = 2;

		var path ='';
		if(this.namespace.substring(0,3) == 'mt.') path = mt.path_mt;
		
		var script  = document.createElement('script');
		script.setAttribute('language','javascript');
		script.setAttribute('type','text/javascript');
		script.setAttribute('src',path+this.file);
		document.getElementsByTagName('head').item(0).appendChild(script);
	}

});

//call constructors
mt.__constructor();
mt.include.__constructor();


