/*
 * Class jsClass
 */
jsClass = Object( "jsClass" );

jsClass.makeClass = function ( name )
{
    /* Create the class */
    var _class = new Function( "",
"if ( this." + name + " )" +
"{" + 
"    var args = new Array();" +
"    for ( var i = 0; i < arguments.length; ++i )" +
"        args.push( arguments[i] );" +
"    this." + name + ".apply( this, args );" +
"}" +
"this._constructing = false;" );

    /* Initialize the class members */
    _class._class = _class;
    _class._name = name;
    _class._parents = new Array();
    for ( var i = 1; i < arguments.length; ++i )
        if ( arguments[i] )
            _class._parents.push( arguments[i] );
    _class._ancestors = new Array();
    _class._ancestor_names = new Array();
    _class._inherit = jsClass._inherit;

    _class.prototype._class = _class;
    _class.prototype._construct = jsClass._construct;
    _class.prototype._call = jsClass._call;
    _class.prototype._constructing = true;

    return _class;
}

jsClass._construct = function ( _class )
{
    if ( typeof( _class ) != "function" )
        alert( "Error: in " + this._class._name + "._construct: _class argument is of type " + typeof( _class ) );

    /* Check if the ancestor has a constructor */
    if ( this[_class._name] == null )
        return;

    /* Create the argument list */
    var args = new Array();
    for ( var i = 1; i < arguments.length; ++i )
        args.push( arguments[i] );

    /* Call the constructor */
    this[_class._name].apply( this, args );
}

jsClass._call = function ( _class, name )
{
    /* Create the argument list */
    var args = new Array();
    for ( var i = 2; i < arguments.length; ++i )
        args.push( arguments[i] );

    /* Find the function */
    var ances = null;
    for ( var a in this._class._ancestors )
    {
        if ( a == _class._name )
        {
            ances = this._class._ancestors[a];
            break;
        }
    }
    if ( ! ances )
        alert( "Ancestor " + _class._name + " not found in class " + this._class._name );

    var func = ances.prototype[name];
    if ( ! func )
        alert( "Method " + name + " not found in class " + this._class._name );

    this._func = func;
    var ret = this._func.apply( this, args );
    this._func = null;
    return ret;
}

jsClass._inherit = function ( )
{
    for ( var i = 0; i < this._parents.length; ++i )
    {
        var parent = this._parents[i];

        /* Fill the ancestors table */
        for ( var ances in parent._ancestors )
            this._ancestors[ances] = parent._ancestors[ances];

        this._ancestors[parent._name] = parent;

        /* Copy the members */
        for ( var member in parent.prototype )
        {
            /* Don't copy the reserved members */
            if ( member == "_class" || member == "_construct" || member == "_call" ||
                 member == "_func" || member == "_constructing" )
                continue;

            /* Check if the member exists in the child class */
            var child_member = this.prototype[member];
            if ( child_member )
            {
                if ( typeof( child_member ) != "function" )
                    alert( "property " + member + " already exists in ancestor " + parent._name );
                continue;
            }

            this.prototype[member] = parent.prototype[member];
        }
    }

    for ( var ances in this._ancestors )
        this._ancestor_names.push( ances ); 
    this._ancestor_names.push( this._name );
}


