diodac
4/15/2015 - 7:03 PM

app_container //CONCEPT

app_container //CONCEPT

app_container.define('ENV_DEV', true);

app_container.set('test_value', 1);
app_container.set('trace', function(msg) {
    console.log(msg);
});

app_container.register('screamer', {
    alert: function(msg) {
        alert(msg);
    }
});

app_container.defer('lazy', function(container) {
    container.run('trace', ['I am lazy']);
    return 'I am not lazy!';
});

app_container.defer('useless', function(container) {
    var msg = container.get('ENV_DEV') ? 'dev' : 'prod';
    return {
        use: function() {
            return msg;
        }
    };
})
var app_container = (function() {
    'use strict';
    
    var registry = {};
    
    var Const = function(value) {
        this.getValue = function() {
            return value;
        }
    }
    
    var Lazy = function(name, fn) {
        this.getParams = function(container) {
            return [name, fn(container)];
        }
    }

    var Value = function(val) {
        this.getValue = function() {
            return val;
        }
    }
    
    function getLazy(container, name) {
        container.register.apply(container, registry[name].getParams(container));
        return container.get(name);
    }
    
    return {
        register: function(name, obj) {
            if (registry[name] && registry[name] instanceof Const) {
                throw 'You can not override constant (' + name + ') value';
            } else if (obj !== undefined) {
                registry[name] = obj;
            }
        },
        set: function(name, obj) {
            this.register(name, new Value(obj));
        },
        define: function(name, obj) {
            this.register(name, new Const(obj));
        },
        defer: function(name, fn) {
            this.register(name, new Lazy(name, fn));
        },
        get: function(name) {
            if (registry[name] instanceof Const) {
                return registry[name].getValue();
            } else if (typeof registry[name] === 'function') {
                return registry[name](this);
            } else if (registry[name] instanceof Value) {
                return registry[name].getValue();
            } else if (registry[name] instanceof Lazy) {
                return getLazy(this, name);
            } else {
                return registry[name];
            }
        },
        run: function(name, args) {
            var fn = this.get(name);
            if (typeof fn !== 'function') {
                throw name + ' is not a function';
            }
            return fn.apply(null, args);
        },
        has: function(name) {
            return registry.hasOwnProperty(name);
        },
        defined: function(name) {
            return this.has(name) && registry[name] instanceof Const;
        },
        showRegistry: function() { //FIXME: remove in production
            return registry;
        },
        reset: function() { //FIXME: remove in production
            registry = {};
        }
    }
})();