/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

define(["util"], function (util) {
  var assert = util.assert;
  var Deferred = util.Deferred;
  var DEFAULT_SETTINGS = {
    name: "",
    defaultName: "",
    avatar: null,
    stickyShare: null,
    color: null,
    seenIntroDialog: false,
    seenWalkthrough: false,
    dontShowRtcInfo: false
  };

  var Storage = util.Class({
    constructor: function (storage, prefix) {
      this.storage = storage;
      this.prefix = prefix;
    },

    get: function (key, defaultValue) {
      var self = this;
      return Deferred(function (def) {
        // Strictly this isn't necessary, but eventually I want to move to something more
        // async for the storage, and this simulates that much better.
        setTimeout(util.resolver(def, function () {
          key = self.prefix + key;
          var value = self.storage.getItem(key);
          if (! value) {
            value = defaultValue;
          } else {
            value = JSON.parse(value);
          }
          return value;
        }));
      });
    },

    set: function (key, value) {
      var self = this;
      return Deferred(function (def) {
        setTimeout(util.resolver(def, function () {
          key = self.prefix + key;
          if (value === undefined) {
            self.storage.removeItem(key);
          } else {
            self.storage.setItem(key, JSON.stringify(value));
          }
        }));
      });
    },

    clear: function () {
      var self = this;
      var promises = [];
      return this.keys().then(function (keys) {
        keys.forEach(function (key) {
          // FIXME: technically we're ignoring the promise returned by all
          // these sets:
          promises.push(self.set(key, undefined));
        });
        return util.resolveMany(promises);
      });
    },

    keys: function (prefix, excludePrefix) {
      // Returns a list of keys, potentially with the given prefix
      var self = this;
      return Deferred(function (def) {
        setTimeout(util.resolver(def, function () {
          prefix = prefix || "";
          var result = [];
          for (var i=0; i<self.storage.length; i++) {
            var key = self.storage.key(i);
            if (key.indexOf(self.prefix + prefix) === 0) {
              var shortKey = key.substr(self.prefix.length);
              if (excludePrefix) {
                shortKey = shortKey.substr(prefix.length);
              }
              result.push(shortKey);
            }
          }
          return result;
        }));
      });
    }

  });

  var storage = Storage(localStorage, "towtruck.");

  storage.settings = util.mixinEvents({
    defaults: DEFAULT_SETTINGS,

    get: function (name) {
      assert(storage.settings.defaults.hasOwnProperty(name), "Unknown setting:", name);
      return Deferred(function (def) {
        storage.get("settings").then(util.resolver(def, function (settings) {
          if ((! settings) || settings[name] === undefined) {
            return storage.settings.defaults[name];
          }
          return settings[name];
        }));
      });
    },

    set: function (name, value) {
      assert(storage.settings.defaults.hasOwnProperty(name), "Unknown setting:", name);
      return Deferred(function (def) {
        storage.get("settings", {}).then(function (settings) {
          var oldValue = settings[name];
          settings[name] = value;
          var def = storage.set("settings", settings);
          storage.settings.emit("change", name, oldValue, value);
          return def;
        });
      });
    }

  });

  storage.tab = Storage(sessionStorage, "towtruck-session.");

  return storage;
});

@@ -503,16 +503,46 @@
 e%0A  %7D;%0A%0A
+  var DEBUG_STORAGE = false;%0A%0A
   var St
@@ -1146,55 +1146,281 @@
     
-%7D else %7B%0A            value = JSON.parse(value);
+  if (DEBUG_STORAGE) %7B%0A              console.debug(%22Get storage%22, key, %22defaults to%22, value);%0A            %7D%0A          %7D else %7B%0A            value = JSON.parse(value);%0A            if (DEBUG_STORAGE) %7B%0A              console.debug(%22Get storage%22, key, %22=%22, value);%0A            %7D
 %0A   
@@ -1758,78 +1758,280 @@
     
-%7D else %7B%0A            self.storage.setItem(key, JSON.stringify(value));
+  if (DEBUG_STORAGE) %7B%0A              console.debug(%22Delete storage%22, key);%0A            %7D%0A          %7D else %7B%0A            self.storage.setItem(key, JSON.stringify(value));%0A            if (DEBUG_STORAGE) %7B%0A              console.debug(%22Set storage%22, key, value);%0A            %7D
 %0A   
@@ -3449,291 +3449,71 @@
 urn 
-Deferred(function (def) %7B%0A        storage.get(%22settings%22).then(util.resolver(def, function (settings) %7B%0A          if ((! settings) %7C%7C settings%5Bname%5D === undefined) %7B%0A            return storage.settings.defaults%5Bname%5D;%0A          %7D%0A          return settings%5Bname%5D;%0A        %7D));%0A      %7D
+storage.get(%22settings.%22 + name, storage.settings.defaults%5Bname%5D
 );%0A 
@@ -3658,50 +3658,16 @@
 urn 
-Deferred(function (def) %7B%0A        
 storage.
 get(
@@ -3654,33 +3654,33 @@
  return storage.
-g
+s
 et(%22settings%22, %7B
@@ -3679,279 +3679,24 @@
 ings
-%22, %7B%7D).then(function (settings) %7B%0A          var oldValue = settings%5Bname%5D;%0A          settings%5Bname%5D = value;%0A          var def = storage.set(%22settings%22, settings);%0A          storage.settings.emit(%22change%22, name, oldValue, value);%0A          return def;%0A        %7D);%0A      %7D
+.%22 + name, value
 );%0A 

Add DEBUG_STORAGE flag. Simplify storage.settings, make each setting its own storage key.