// ========================================================================
// SproutCore
// copyright 2006-2008 Sprout Systems, Inc.
// ========================================================================

require('core') ;
require('system/object');

/**
  @class
  
  The UserDefaults object provides an easy way to store user preferences in
  your application on the local machine.  You use this by providing built-in
  defaults using the SC.userDefaults.defaults() method.  You can also
  implement the UserDefaultsDelegate interface to be notified whenever a
  default is required.  
  
  You should also set the userDomain property on the defaults on page load.
  This will allow the UserDefaults application to store/fetch keys from 
  localStorage for the correct user.
  
  You can also set an appDomain property if you want.  This will be 
  automatically prepended to key names with no slashes in them.
  
  SC.userDefaults.getPath("global:contactInfo.userName");
  
  @extends SC.Object
  @since SproutCore 1.0
*/
SC.UserDefaults = SC.Object.extend({
  
  /** 
    the default domain for the user.  This will be used to store keys in
    local storage.  If you do not set this property, the wrong values may be
    returned.
  */
  userDomain: null,
  
  /**
    The default app domain for the user.  Any keys that do not include a 
    slash will be prefixed with this app domain key when getting/setting.
  */
  appDomain: null,
  
  /** @private
    Defaults.  These will be used if not defined on localStorage.
  */
  _defaults: null,
  
  /**
    Invoke this method to set the builtin defaults.  This will cause all
    properties to change.
  */
  defaults: function(newDefaults) {
    this._defaults = newDefaults ;
    this.allPropertiesDidChange();
  },
  
  /**
    Attempts to read a user default from local storage.  If not found on 
    localStorage, use the the local defaults, if defined.  If the key passed
    does not include a slash, then add the appDomain or use "app/".
    
    @param {String} keyName
    @returns {Object} read value
  */
  readDefault: function(keyName) {
    var ret= undefined ;
    
    // namespace keyname
    if (keyName.indexOf('/')) {
      var domain = this.get('appDomain') || 'app';
      keyName = [domain, keyName].join('/');
    } 
    
    var user = this.get('userDomain') || '' ;
    var userKeyName = [user,keyName].join('@');

    // look into recently written values
    if (this._written) ret = this._written[userKeyName];
    
    // attempt to read from localStorage
    if (window.localStorage) {
      ret = window.localStorage[["SC.UserDefaults",userKeyName].join('@')];
    }
    
    // if not found in localStorage, try to notify delegate
    var del =this.delegate ;
    if (del && del.userDefaultsNeedsDefault) {
      ret = del.userDefaultsNeedsDefault(this, keyName, userKeyName);
    }
    
    // if not found in localStorage or delegate, try to find in defaults
    if ((ret===undefined) && this._defaults) {
      ret = this._defaults[userKeyName] || this._defaults[keyName];
    }
    
    return ret ;
  },
  
  /**
    Attempts to write the user default to local storage or at least saves them
    for now.  Also notifies that the value has changed.
    
    @param {String} keyName
    @param {Object} value
    @returns {SC.UserDefault} receiver
  */
  writeDefault: function(keyName, value) {
    // namespace keyname
    if (keyName.indexOf('/')) {
      var domain = this.get('appDomain') || 'app';
      keyName = [domain, keyName].join('/');
    } 
    
    var user = this.get('userDomain') || '' ;
    var userKeyName = [user,keyName].join('@');

    // save to local hash
    var written = this._written ;
    if (!written) written = this._written = {};
    written[userKeyName] = value ;
    
    // save to local storage
    if (window.localStorage) {
      window.localStorage[["SC.UserDefaults",userKeyName].join('@')] = value;
    }
    
    // also notify delegate
    var del = this.delegate;
    if (del && del.userDefaultsDidChange) {
      del.userDefaultsDidChange(this, keyName, value, userKeyName);
    }
    
    return this ;
  },
  
  unknownProperty: function(key, value) {
    if (value === undefined) {
      return this.readDefault(key) ;
    } else {
      this.writeDefault(key, value);
      return value ;
    }
  }
  
});

/** global user defaults. */
SC.userDefaults = SC.UserDefaults.create();
@@ -2276,33 +2276,33 @@
  keyName%5D.join('
-/
+:
 ');%0A    %7D %0A    %0A
@@ -2540,38 +2540,101 @@
 Storage%0A    
-if (
+var localStorage = window.localStorage ;%0A    if (!localStorage && 
 window.
+g
 lo
-c
+b
 alStorage) %7B
@@ -2644,21 +2644,192 @@
     
-ret = window.
+localStorage = window.globalStorage%5Bwindow.location.hostname%5D;%0A    %7D%0A    if (localStorage) %7B%0A      console.log('userKeyName = %25@ local=%25@'.fmt(userKeyName, localStorage));%0A      ret = 
 loca
@@ -3768,17 +3768,17 @@
 %5D.join('
-/
+:
 ');%0A    
@@ -4065,22 +4065,85 @@
     
-if (
+var localStorage = window.localStorage ;%0A    if (!localStorage && 
 window.
+g
 lo
-c
+b
 alSt
@@ -4157,23 +4157,115 @@
 %7B%0A      
-window.
+localStorage = window.globalStorage%5Bwindow.location.hostname%5D;%0A    %7D%0A    if (localStorage) %7B%0A      
 localSto

Add support for globalStorage in FireFox to user defaults. Seems not to work quite yet...