var App = App || {};

App.DI = (function() {

    var factories = {};
    var instances = {};

    function get(key) {
        var instance = instances[key];
        if (!instance) {
            var factory = factories[key];
            if (!factory) {
                throw new Error('Unregistered key: ' + key);
            }
            var objectInitializer = factory.initializer;
            var singleton = factory.singleton;
            var deps = resolveDependencies(objectInitializer, factory.dependencies);
            instance = {};
            instance = objectInitializer.apply(instance, deps);
            if (singleton) {
                instances[key] = instance;
            }
        }
        return instance;
    }

    function resolveDependencies(objectIntializer, depKeys) {
        var deps = [];
        for (var i = 0; i < depKeys.length; i ++) {
            deps[i] = get(depKeys[i]);
        }
        return deps;
    }

    function register(key, dependencies, objectInitializer) {
        factories[key] = {initializer: objectInitializer, singleton: false, dependencies: dependencies};
    }

    function registerSingleton(key, dependencies, objectInitializer) {
        factories[key] = {initializer: objectInitializer, singleton: true, dependencies: dependencies};
    }

    function registerManual(key, objectInitializer) {
        instances[key] = objectInitializer();
    }

    return {
        get: get,
        register: register,
        registerManual: registerManual,
        registerSingleton: registerSingleton,
    };

})();