"use strict";

App.module("DataModule", function(DataModule, App, Backbone, Marionette, $, _, Logger) {

    DataModule.addInitializer(function(){
        //var logger = Logger.get("DataModule.DynamicDefinition");

        DataModule.DynamicDefinition = DataModule.ModelWithHashableAttributes.extend({
            
            initialize: function(attributes, options) {
                DataModule.ModelWithHashableAttributes.prototype.initialize.apply(this, arguments);
                
                this._entityConfig = options.entityConfig;
                this._provider = options.provider;
                this._cachedRequestHash = "{}";
                
                this.listenTo(this._entityConfig, "change:parameters", this.update);
                this.update();
            },
            
            update: function(force) {
                var parameterHash = this._entityConfig.getHashForParameters();
                var requestHash = this._provider._requestHashesByParameterHash[parameterHash];
                if (!requestHash) {
                    var requestParameters = this._provider.configParametersToRequestParameters(this._entityConfig);
                    requestHash = JSON.stringify(requestParameters);
                    this._provider._requestHashesByParameterHash[parameterHash] = requestHash;
                    this._provider._requestParametersByRequestHash[requestHash] = requestParameters;
                }
                
                if (requestHash == this._cachedRequestHash && !force) {
                    return;
                }
                
                if (requestHash !== this._cachedRequestHash) {
                    if (this._cachedRequestHash) {
                        this.stopListening(this._provider, "change:" + this._cachedRequestHash, this._applyCachedAttributes);
                    }
                    this._cachedRequestHash = requestHash;
                    this.listenTo     (this._provider, "change:" + this._cachedRequestHash, this._applyCachedAttributes);
                }
                
                if (this._provider._cachedAttributesByRequestHash[this._cachedRequestHash] && !force) {
                    this._applyCachedAttributes();
                } else {
                    this._provider.updateResponseForRequestHash(requestHash);
                };
            },
            
            _applyCachedAttributes: function() {
                var definitionAttributes =  this._provider._cachedAttributesByRequestHash[this._cachedRequestHash];
                if (_.isUndefined(definitionAttributes)) {
                    throw _.str.sprintf("Unexpected cached attributes for DynamicDefinition to be undefined");
                }
                
                if (!_.isEqual(this.attributes, definitionAttributes)) {
                    this.attributes = definitionAttributes;
                    this.trigger("change");
                }
            }
        });
    });
    
}, Logger);
