/***
 * extends a first object with the properties of next passed objects.
 * @param {Class/Object} clazz the class to be extended.
 * @params {Class/Object...} superclass the superclass
 */
Object.extend = function(clazz) {
	if(!clazz) 
		return null;
	var mfunc = typeof(clazz) == "function";
	var mproto = mfunc ? clazz.prototype : clazz;
	for(var i=1; i<arguments.length; i++){
		if(arguments[i]) {
			var superobj = arguments[i], isfunc;
			var proto = (isfunc = typeof(superobj) == "function") ? superobj.prototype : superobj;
			for(var p in proto){
				if(!this.keywords || !this.keywords[p]) {
					var pname = p;		 
					if(!mfunc || typeof mproto[pname] == "undefined")
						mproto[pname]=proto[p];
				}
			}
		}
	}
	return clazz;	
};
/*
    Utility class for implementing class inheritance in Javascript.
    -----------------------------------------------------------------------
    Usage:
	  <class-name>=Class.create(<super-class>,<constructor|JONS>);
	Example:
	  MyClass=Class.create({
	    superclass	: SuperClass,
	    constructor: function(name){
	      this.name=name;
	    },
	    getName=function(){
	      return this.name;
	    }
	  });
*/
Class = {
  /**Stack of current supercalls */
  // supercallStack: [],
  // reserved words in class configuration.
  keywords		: {
	constructor	: true,
	superclass	: true,
	_class		: true,
	_className 	: true,
	class$name  : true
  },		
  /**
     Creates a new class.  Adds instanceOf and supercall methods for type checking
     and accessing methods of super classes
          className: name of new class
          superclass: class that the new class will extend
          constructor: class constructor
  */
  create: function() {
	var clazz, superclass=[], constructor;
	var config=arguments.length>0 ? arguments[arguments.length-1] : {};
	for(var i=0; i<arguments.length-1; i++)
		superclass[superclass.length]=arguments[i];
	if(config.superclass){
		if(!this.isArray(config.superclass))
			superclass[superclass.length]=config.superclass;
		else
			superclass.concat(config.superclass);
	}
	constructor = typeof config == "function" ? config : config.constructor;
	// Create the class
	if(typeof constructor != "function") {
		clazz = function() {};
	} else 
		clazz = constructor;
	// set the constructor of class
	clazz.prototype.constructor = clazz;
	clazz.prototype._class = clazz;
	clazz.prototype._className = config.class$name;
	// If a superclass is given then inherit the prototype and set the
	// superclass property on the prototype.
	if (superclass){
	  for(var i=0; i<superclass.length; i++){
		var yproto = typeof(superclass[i]) == "function" ? superclass[i].prototype : superclass[i];
		Object.extend.apply(this,[typeof config == "function" ? clazz : clazz.prototype, yproto]);
		if(!clazz.superclass)
			clazz.superclass = typeof superclass[i] == "function" ? superclass[i] : this.create(superclass[i]);
		else{
			if(clazz.implements == null) clazz.implements=[];
			clazz.implements[clazz.implements.length]=
				typeof superclass[i] == "function" ? superclass[i] : this.create(superclass[i]);
		}		
	  }
	}
	if(typeof config != "function")
		Object.extend.apply(this,[clazz.prototype, config]);
	clazz.prototype.toString=Class.toString;
	/***
	 * returns the class of object.
	 * @return
	 */
	clazz.prototype.getClass=function() {
		return this._class;
	};
	/** 
	 * call the class constructor.
	 */
	clazz.call=function(me) {
		var args=[];
		for(var i=1;i<arguments.length;i++)
			args[args.length]=arguments[i];
		this.prototype.constructor.apply(me,args);
	};	
	/***
	 * returns true if the passed object is an instance of the class.
	 */
	clazz.instanceOf = function(obj){
		return Class.instanceOf(obj,this);
	};
	// Return the new class.
	return clazz;
  },
  /** Returns true if the given object is an instance of the given class.
      JavaScript 1.5 has instanceof built in, but here is an implementation for older browsers
            obj: object to test
            clazz: class to test against
  */
  instanceOf: function(obj, clazz) {
	  if(obj==null)
		  return false;
	  var proto = (typeof(obj)=="function"? obj : (obj._class? obj._class: obj.constructor));
	  if(!proto)
		  return false;
	  return Class.isAssignableFrom(clazz,proto);
  },
  /**
   * il metodo ritorna true se la prima classe e' assegnabile dalla seconda.
   */
  isAssignableFrom:function(clazz,from){
	    var superclasses=[from];
	    for(var i=0; i < superclasses.length; i++){
		  var proto = superclasses[i];
		  while (proto) {
			if (proto == clazz) 
				return true;
			proto = proto.superclass || null;
		  }
	    }
		return false;  
  },
  /**
   * the default bean setter.
   */
  set:function (name,value){
		var setname="set"+name.substring(0,1).toUpperCase()+name.substring(1,name.length);
		if(typeof(this.constructor.prototype[setname])=="function")
			return this.constructor.prototype[setname].apply(this,[value]);
		else if(this.setter)
			return this.setter(name,value);
		else
			return(this[name]=value);
  },
  /**
   * the default bean getter
   */
  get:function (name){
		var getname="get"+name.substring(0,1).toUpperCase()+name.substring(1,name.length);
		if(typeof(this.constructor.prototype[getname])=="function")
			return this.constructor.prototype[getname].apply(this,[]);
		else if(typeof(this.getter)=="function")
			return this.getter(name);
		else
			return this[name];
  },     
  /** 
   * test if the input object is primitive 
   */
  isPrimitive:function(object){
    return (typeof(object)=="string" || typeof(object)=="number");
  },
  /** test if the input object class is an array */
  isArray:function(object){
    return (object.constructor == Array);
  }  
};
/** 
 * Task class
 */
Task=Class.create({
  object	: window,
  method	: null,
  arguments	: new Array(),
  timeout	: 0,
  /** constructor of task */
  constructor:function Task(object,method) {
    if(object!=null) this.object=object;
    if(typeof(this.method)=="string"){
      if(typeof(this.object[this.method])=="function")
    	  this.method=this.object[this.method];
    	else
    	  throw new Error("Method: "+this.method+" not found!");
    }
    else if(typeof(method)=="function")    
      this.method=method;
    else
      throw new Error("Method: "+method+" invalid!");
    for(var i=2;i<arguments.length;i++) 
    	args[args.length]=arguments[i];
  },
  /** start the task */
  start:function() {
    if(this.arguments.length==0 && arguments.length>0)
      for(var i=0; i<arguments.length;i++)
      	this.arguments[this.arguments.length]=arguments[i];
    return this.method.apply(this.object,this.arguments);
  }
});
