/**
 * Limited cache is a size limited cache container that stores limited number of objects.
 * 
 * When {@link #get} is called, the container will try to find the object in the list.
 * If failed it will call the {@link #feeder} to create that object. If there are too many
 * objects in the container, the old ones are removed.
 * 
 * __Note:__ This is not using a Least Recently Used policy due to simplicity and performance consideration.
 * @private
 */
Ext.define('Ext.draw.LimitedCache', {
 
    config: {
        /**
         * @cfg {Number}
         * The amount limit of the cache.
         */
        limit: 40,
 
        /**
         * @cfg {Function}
         * Function that generates the object when look-up failed.
         * @return {Number}
         */
        feeder: function () {
            return 0;
        },
 
        /**
         * @cfg {Object}
         * The scope for {@link #feeder}
         */
        scope: null
    },
 
    cache: null,
 
    constructor: function (config) {
        this.cache = {};
        this.cache.list = [];
        this.cache.tail = 0;
        this.initConfig(config);
    },
 
    /**
     * Get a cached object.
     * @param {String} id 
     * @return {Object}
     */
    get: function (id) {
        // TODO: Implement cache hit optimization 
        var cache = this.cache,
            limit = this.getLimit(),
            feeder = this.getFeeder(),
            scope = this.getScope() || this;
 
        if (cache[id]) {
            return cache[id].value;
        }
        if (cache.list[cache.tail]) {
            delete cache[cache.list[cache.tail].cacheId];
        }
        cache[id] = cache.list[cache.tail] = {
            value: feeder.apply(scope, Array.prototype.slice.call(arguments, 1)),
            cacheId: id
        };
        cache.tail++;
        if (cache.tail === limit) {
            cache.tail = 0;
        }
        return cache[id].value;
    },
 
    /**
     * Clear all the objects.
     */
    clear: function () {
        this.cache = {};
        this.cache.list = [];
        this.cache.tail = 0;
    }
});