function debug(str){
	//console.log(str);
}

nad = {
	Version: '0.1',
	Interface: function(name, funcNames){
		if(arguments.length != 2){
			throw new Error('Interface constructor expects 2 arguments.');
		}
		this.name = name;
		this.methods = funcNames;
	},
	Klasse: function(){
		var args = $A(arguments),
				name = args.shift(),
				parent = arguments.length == 3 ? args.shift() : false,
				klass = args.shift();


		if (parent) {
			/** warum kein prototype-chain
			* warum nicht einfach den prototype chain nehmen fuer vererbung via
			* klass.prototype = new parent;
			* - kein aufruf des parent.constructors im klassischem sinne, da dies dann eigene variablen initialisiert
			* 	denn der aufruf des parent-constructors ist quasi statisch, aendert also die variablen fuer alle geschwister
			* -> also eigenen konstruktor bauen, der dann fuer alle handish aufgerufen werden muss
			* -> zugriff auf parent ermoeglichen
			* => dadurch aber kein prototype-chain
			* -> also eigene impl. von instanceof durch is()
			*/
			var chain = parent.chain();
			chain.push(name);
			klass.chain = function(){
				return chain;
			};
			klass.prototype.is = function(klassName){
				return $.inArray(klassName, chain) != -1;
			};
      klass.base = parent;
    }else{
    	klass.chain = function(){
    		return [name];
    	};
    	klass.prototype.is = function(klassName){
				return klassName == name;
		};
    }

    if(!klass.prototype.construct){
    	klass.prototype.construct = function(){};
    }

		klass.prototype.toString = function(){ 
			return name; 
		};
		return klass;
	},
	Object: function(){
		var args = $A(arguments),
				klass = args.shift(),
				obj = new klass();
		nad.ObjectChain(obj, klass);
		obj.construct.apply(obj, args);
		return obj;
	},
	ObjectChain:function(obj, Klasse){
		if(Klasse.base){
			var parentObjekt = new Klasse.base();

			nad.ObjectChain(parentObjekt, Klasse.base);

			obj.base = parentObjekt;
			for(prop in parentObjekt){
				//debug(obj.toString() + ' erbe oder ueberschreibe: ' + prop);
				if(!obj[prop]){ // keine eigenschaft also erben
					obj[prop] = parentObjekt[prop];
					if(typeof obj[prop] == 'function'){
						obj[prop].owner = obj;
					}
					//debug('erbe')
				}else if(prop != 'construct'){ // achtung nicht den konstruktor ueberschreiben
					if(typeof obj[prop] == 'function'){
						parentObjekt[prop].owner = obj;
						obj[prop].base = parentObjekt[prop]; // ueberschriebene eigenschaft, daher auch lassen, aber als base hinzufuegen
					}
					//debug('ueberschreibe');
				}

			}
		}
	},
	ducktyping: function(obj, iface){
		for(var m = 0; m < iface.methods.length; m++){
			if(!obj[iface.methods[m]] || typeof obj[iface.methods[m]] != 'function'){
				throw new Exception('BuildError','objects of this type must define ' + iface.methods[m] + ' as method if they implemts ' + iface.name);
			}
		}
	}
};
nad.Klasse.toString = function(){
	return 'nad.Klasse';
};
Exception = nad.Klasse('Exception', function(){
	var self = this;
	this.type = arguments.length == 2 ? arguments[0] : 'Exception';
	this.name = this.type;
	this.message = arguments.length == 2 ? arguments[1] : arguments[0];
	this.getType = function(){
		return self.type;
	};
	this.getName = function(){
		return self.type;
	};
	this.getMessage = function(){
		return self.message;
	};
	this.toString = function(){
		return self.name + ": " + self.message;
	};
});
function $A(iterable) {
  if (!iterable) return [];
  if (iterable.toArray) return iterable.toArray();
  var length = iterable.length, results = new Array(length);
  while (length--) results[length] = iterable[length];
  return results;
}
