// proto.js
// 
// Copyright (c) 2010 Guillaume Lathoud
// MIT License

/*global from proto*/

(function () {
    var _proto_only = false;
    
    /*global*/proto = function (/*function*/Ctor) {
        // Returns a prototype object, instanceof Ctor.
        // (The object is only meant to be used as a prototype.)
        _proto_only = true;
        try {
            var ret     = new Ctor();
        } finally {
            _proto_only = false;
        }
        return ret;
    };
    
    proto.Ctor = function ( /*?function | object?*/ parent, 
        /*?function?*/ Ctor_impl, 
        /*?object?*/ interface_0, /*?object?*/ interface_1 /*, etc. */)
    {
        // Single inheritance:
        // - classical:  `parent` is a function: `Parent_Ctor`.
        // - prototypal: `parent` is an object.
        // 
        // (If you need multiple "class" inheritance, have `Ctor_impl`
        // explicitly apply the constructors of `interface_0`, etc.).
        
        var Parent_Ctor = (typeof parent === 'function') && parent
        , Ctor          = function (/*...*/) 
        {
            if (_proto_only) return;
            if (Parent_Ctor) Parent_Ctor.apply(this, arguments);
            if (Ctor_impl)   Ctor_impl.apply(this, arguments);
        }
        , interface_arr = Array.prototype.slice.call( arguments, 2 )
        , Cp            = Ctor.prototype = 
            (Parent_Ctor ? proto(Parent_Ctor) : parent) || {}
        ;
        while (interface_arr.length) {
            var k, i = interface_arr.shift();
            if (i) {
                for (k in i) Cp[k] = i[k];
            }
        }
        return Ctor;
    };

    // Delegation (a.k.a. Crockford's prototypal inheritance)
    proto.obj = function (/*object*/o) { return new proto.Ctor(o); };
})();

if (typeof from !== 'undefined') // Optional integration within from.js
    from.req.done('proto', true);

