"use strict";

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

    // Define private variables
    var logger = null;

    ContextModule.addInitializer(function(options){

        logger = Logger.get("ContextModule.State");
        logger.setLevel(Logger.WARN);

        /**
         * State stores the configuration of the entire vis interface, i.e.
         * the contents of both entity config grids (collections & recordings)
         *
         * The state can be serialized and unserialized, and this allows for
         * undo / redo mechanism to be implemented.
         */
        ContextModule.State = Backbone.Model.extend({
            defaults: {
                musicCollectionGrid: null,
                musicRecordingGrid: null
            },

            /**
             * @memberOf App.ContextModule.State
             */
            initialize: function() {
                this._modificationPropagationEnabled = true;
                this._attributesWereModified = false;

                this.attributes.musicCollectionGrid = new ContextModule.ConfigGrid("collection");
                this.attributes.musicRecordingGrid = new ContextModule.ConfigGrid("recording");

                this.attributes.musicCollectionGrid.bind("change", this._registerModificationOfAttribute, this);
                this.attributes.musicRecordingGrid.bind("change", this._registerModificationOfAttribute, this);
            },

            /**
             * @memberOf App.ContextModule.State
             */
            getConfigGridByType: function(type) {
                switch (type) {
                    case "recordings":
                        return this.attributes.musicRecordingGrid;
                    case "collections":
                        return this.attributes.musicCollectionGrid;
                    default:
                        return null;
                }
            },

            /**
             * @memberOf App.ContextModule.State
             */
            getConfigGridBeingShown: function() {
                return this.attributes.musicRecordingsGridIsShown
                    ? this.attributes.musicRecordingGrid
                    : this.attributes.musicCollectionGrid;
            },

            /**
             * @memberOf App.ContextModule.State
             */
            serialize: function() {
                logger.debug("method called: State::serialize");

                var result = {
                        musicCollectionGrid: this.attributes.musicCollectionGrid.serialize(),
                        musicRecordingGrid: this.attributes.musicRecordingGrid.serialize()
                };

                if (this.attributes.musicRecordingsGridIsShown) {
                    result.musicRecordingsGridIsShown = true;
                }

                return result;
            },

            /**
             * @memberOf App.ContextModule.State
             */
            unserialize: function(serializedAttributes) {
                logger.debug("method called: State::unserialize");
                this._modificationPropagationEnabled = false;
                this._attributesWereModified = false;

                var fixedSerializedAttributes = serializedAttributes;
                if (!_.isSimpleObject(fixedSerializedAttributes)) {
                    logger.warn("State::unserialize called for not an object: ", serializedAttributes);
                    fixedSerializedAttributes = {};
                }
                this.attributes.musicCollectionGrid.unserialize(fixedSerializedAttributes.musicCollectionGrid);
                this.attributes.musicRecordingGrid.unserialize(fixedSerializedAttributes.musicRecordingGrid);

                if (this.attributes.musicRecordingsGridIsShown !== fixedSerializedAttributes.musicRecordingsGridIsShown) {
                    this._attributesWereModified = true;
                }
                if (fixedSerializedAttributes.musicRecordingsGridIsShown) {
                    this.attributes.musicRecordingsGridIsShown = true;
                } else {
                    delete this.attributes.musicRecordingsGridIsShown;
                }

                this._triggerModificationEventsIfNeeded();
                this._modificationPropagationEnabled = true;
            },

            _registerModificationOfAttribute: function() {
                this._attributesWereModified = true;
                if (this._modificationPropagationEnabled) {
                    this._triggerModificationEventsIfNeeded();
                };
            },

            _triggerModificationEventsIfNeeded: function() {
                if (this._attributesWereModified) {
                    this.trigger("change");
                }
                this._attributesWereModified = false;
            },
        });

    });
}, Logger);
