/*
 * Builder client-side plugin data registry
 */
+function ($) { "use strict";

    if ($.wn.builder === undefined)
        $.wn.builder = {}

    var Base = $.wn.foundation.base,
        BaseProto = Base.prototype

    var DataRegistry = function() {
        this.data = {}
        this.requestCache = {}
        this.callbackCache = {}

        Base.call(this)
    }

    /*
     * Example:
     * $.wn.builder.dataRegistry.set('winter.blog', 'model.forms', 'Categories', formsArray)
     * $.wn.builder.dataRegistry.set('winter.blog', 'localization', null, stringsArray) // The registry contains only default language
     */
    DataRegistry.prototype.set = function(plugin, type, subtype, data, params) {
        this.storeData(plugin, type, subtype, data)

        if (type == 'localization' && !subtype) {
            this.localizationUpdated(plugin, params)
        }
    }

    /*
     * Example:
     * $.wn.builder.dataRegistry.get($form, 'winter.blog', 'model.forms', 'Categories', function(data){ ... })
     */
    DataRegistry.prototype.get = function($formElement, plugin, type, subtype, callback) {
        if (this.data[plugin] === undefined
            || this.data[plugin][type] === undefined
            || this.data[plugin][type][subtype] === undefined
            || this.isCacheObsolete(this.data[plugin][type][subtype].timestamp)) {

            return this.loadDataFromServer($formElement, plugin, type, subtype, callback)
        }

        callback(this.data[plugin][type][subtype].data)
    }

    // INTERNAL METHODS
    // ============================

    DataRegistry.prototype.makeCacheKey = function(plugin, type, subtype) {
        var key = plugin + '-' + type

        if (subtype) {
            key += '-' + subtype
        }

        return key
    }

    DataRegistry.prototype.isCacheObsolete = function(timestamp) {
        return (Date.now() - timestamp) > 60000*5 // 5 minutes cache TTL
    }

    DataRegistry.prototype.loadDataFromServer = function($formElement, plugin, type, subtype, callback) {
        var self = this,
            cacheKey = this.makeCacheKey(plugin, type, subtype)

        if (this.requestCache[cacheKey] === undefined) {
            this.requestCache[cacheKey] = $formElement.request('onPluginDataRegistryGetData', {
                data: {
                    registry_plugin_code: plugin,
                    registry_data_type: type,
                    registry_data_subtype: subtype
                }
            }).done(
                function(data) {
                    if (data.registryData === undefined) {
                        throw new Error('Invalid data registry response.')
                    }

                    self.storeData(plugin, type, subtype, data.registryData)
                    self.applyCallbacks(cacheKey, data.registryData)

                    self.requestCache[cacheKey] = undefined
                }
            )
        }

        this.addCallbackToQueue(callback, cacheKey)

        return this.requestCache[cacheKey]
    }

    DataRegistry.prototype.addCallbackToQueue = function(callback, key) {
        if (this.callbackCache[key] === undefined) {
            this.callbackCache[key] = []
        }

        this.callbackCache[key].push(callback)
    }

    DataRegistry.prototype.applyCallbacks = function(key, registryData) {
        if (this.callbackCache[key] === undefined) {
            return
        }

        for (var i=this.callbackCache[key].length-1; i>=0; i--) {
            this.callbackCache[key][i](registryData);
        }

        delete this.callbackCache[key]
    }

    DataRegistry.prototype.storeData  = function(plugin, type, subtype, data) {
        if (this.data[plugin] === undefined) {
            this.data[plugin] = {}
        }

        if (this.data[plugin][type] === undefined) {
            this.data[plugin][type] = {}
        }

        var dataItem = {
            timestamp: Date.now(),
            data: data
        }

        this.data[plugin][type][subtype] = dataItem
    }

    DataRegistry.prototype.clearCache = function(plugin, type) {
        if (this.data[plugin] === undefined) {
            return
        }

        if (this.data[plugin][type] === undefined) {
            return
        }

        this.data[plugin][type] = undefined
    }

    // LOCALIZATION-SPECIFIC METHODS
    // ============================

    DataRegistry.prototype.getLocalizationString = function($formElement, plugin, key, callback) {
        this.get($formElement, plugin, 'localization', null, function(data){
            if (data[key] !== undefined) {
                callback(data[key])
                return
            }

            callback(key)
        })
    }

    DataRegistry.prototype.localizationUpdated = function(plugin, params) {
        $.wn.builder.localizationInput.updatePluginInputs(plugin)

        if (params === undefined || !params.suppressLanguageEditorUpdate) {
            $.wn.builder.indexController.entityControllers.localization.languageUpdated(plugin)
        }

        $.wn.builder.indexController.entityControllers.localization.updateOnScreenStrings(plugin)
    }

    $.wn.builder.dataRegistry = new DataRegistry()
}(window.jQuery);