<!DOCTYPE html>
<!--
Copyright (c) 2013 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<link rel="import" href="/base/settings.html">

<script>
'use strict';

tr.exportTo('tr.model', function() {
  var Settings = tr.b.Settings;

  /**
   * A way to persist settings specific to parts of a trace model.
   *
   * This object should not be persisted because it builds up internal data
   * structures that map model objects to settings keys. It should thus be
   * created for the duration of whatever interaction(s) you're going to do with
   * model settings, and then discarded.
   *
   * This system works on a notion of an object key: for an object's key, it
   * considers all the other keys in the model. If it is unique, then the key is
   * persisted to tr.b.Settings. However, if it is not unique, then the
   * setting is stored on the object itself. Thus, objects with unique keys will
   * be persisted across page reloads, whereas objects with nonunique keys will
   * not.
   */
  function ModelSettings(model) {
    this.model = model;
    this.objectsByKey_ = [];
    this.nonuniqueKeys_ = [];
    this.buildObjectsByKeyMap_();
    this.removeNonuniqueKeysFromSettings_();
    this.ephemeralSettingsByGUID_ = {};
  }

  ModelSettings.prototype = {
    buildObjectsByKeyMap_: function() {
      var objects = [];
      this.model.iterateAllPersistableObjects(function(o) {
        objects.push(o);
      });

      var objectsByKey = {};
      var NONUNIQUE_KEY = 'nonuniqueKey';
      for (var i = 0; i < objects.length; i++) {
        var object = objects[i];
        var objectKey = object.getSettingsKey();
        if (!objectKey)
          continue;
        if (objectsByKey[objectKey] === undefined) {
          objectsByKey[objectKey] = object;
          continue;
        }
        objectsByKey[objectKey] = NONUNIQUE_KEY;
      }

      var nonuniqueKeys = {};
      tr.b.dictionaryKeys(objectsByKey).forEach(function(objectKey) {
        if (objectsByKey[objectKey] !== NONUNIQUE_KEY)
          return;
        delete objectsByKey[objectKey];
        nonuniqueKeys[objectKey] = true;
      });

      this.nonuniqueKeys = nonuniqueKeys;
      this.objectsByKey_ = objectsByKey;
    },

    removeNonuniqueKeysFromSettings_: function() {
      var settings = Settings.get('trace_model_settings', {});
      var settingsChanged = false;
      tr.b.dictionaryKeys(settings).forEach(function(objectKey) {
        if (!this.nonuniqueKeys[objectKey])
          return;
        settingsChanged = true;
        delete settings[objectKey];
      }, this);
      if (settingsChanged)
        Settings.set('trace_model_settings', settings);
    },

    hasUniqueSettingKey: function(object) {
      var objectKey = object.getSettingsKey();
      if (!objectKey)
        return false;
      return this.objectsByKey_[objectKey] !== undefined;
    },

    getSettingFor: function(object, objectLevelKey, defaultValue) {
      var objectKey = object.getSettingsKey();
      if (!objectKey || !this.objectsByKey_[objectKey]) {
        var settings = this.getEphemeralSettingsFor_(object);
        var ephemeralValue = settings[objectLevelKey];
        if (ephemeralValue !== undefined)
          return ephemeralValue;
        return defaultValue;
      }

      var settings = Settings.get('trace_model_settings', {});
      if (!settings[objectKey])
        settings[objectKey] = {};
      var value = settings[objectKey][objectLevelKey];
      if (value !== undefined)
        return value;
      return defaultValue;
    },

    setSettingFor: function(object, objectLevelKey, value) {
      var objectKey = object.getSettingsKey();
      if (!objectKey || !this.objectsByKey_[objectKey]) {
        this.getEphemeralSettingsFor_(object)[objectLevelKey] = value;
        return;
      }

      var settings = Settings.get('trace_model_settings', {});
      if (!settings[objectKey])
        settings[objectKey] = {};
      if (settings[objectKey][objectLevelKey] === value)
        return;
      settings[objectKey][objectLevelKey] = value;
      Settings.set('trace_model_settings', settings);
    },

    getEphemeralSettingsFor_: function(object) {
      if (object.guid === undefined)
        throw new Error('Only objects with GUIDs can be persisted');
      if (this.ephemeralSettingsByGUID_[object.guid] === undefined)
        this.ephemeralSettingsByGUID_[object.guid] = {};
      return this.ephemeralSettingsByGUID_[object.guid];
    }
  };

  return {
    ModelSettings: ModelSettings
  };
});
</script>
