

function addSingletonGetter(ctor) {
  ctor.getInstance = function() {
    return ctor.instance_ || (ctor.instance_ = new ctor());
  };
}

function Preferences() {
  // Map of registered preferences.
  this.registeredPreferences_ = {};
}

 Preferences.prototype.setPrefNoCommit_ = function(name, type, value) {
  var pref = this.registeredPreferences_[name];
  pref.action = 'set';
  pref.type = type;
  pref.value = value;
},


    /**
     * Commits a preference change to Chrome and signals the new preference
     * value. Does nothing if there is no uncommitted change.
     * @param {string} name Preference name.
     * @param {string} metric User metrics identifier.
     */
Preferences.prototype.commitPref = function(name, metric) {
  var pref = this.registeredPreferences_[name];
  switch (pref.action) {
    case 'set':
      switch (pref.type) {
        case 'bool':
          Preferences.setBooleanPref(name, pref.value, true, metric);
          break;
        case 'int':
          Preferences.setIntegerPref(name, pref.value, true, metric);
          break;
        case 'double':
          Preferences.setDoublePref(name, pref.value, true, metric);
          break;
        case 'string':
          Preferences.setStringPref(name, pref.value, true, metric);
          break;
        case 'url':
          Preferences.setURLPref(name, pref.value, true, metric);
          break;
        case 'list':
          Preferences.setListPref(name, pref.value, true, metric);
          break;
      }
      break;
    case 'clear':
      Preferences.clearPref(name, true, metric);
      break;
  }
  delete pref.action;
  delete pref.type;
  delete pref.value
};

    /**
     * Clears a preference and signals its new value. The change is propagated
     * throughout the UI code but is not committed to Chrome yet.
     * @param {string} name Preference name.
     * @private
     */
Preferences.prototype.clearPrefNoCommit_ =  function(name) {
  var pref = this.registeredPreferences_[name];
  pref.action = 'clear';
  delete pref.type;
  delete pref.value;
};

/**
 * Rolls back a preference change and signals the original preference value.
 * Does nothing if there is no uncommitted change.
 * @param {string} name Preference name.
 */
Preferences.prototype.rollbackPref = function(name) {
  var pref = this.registeredPreferences_[name];
  if (!pref.action)
    return;

  delete pref.action;
  delete pref.type;
  delete pref.value;
/*
  var event = new cr.Event(name);
  event.value = pref.orig;
  event.value.uncommitted = true;
  this.dispatchEvent(event);
*/
}
    
/**
 * Sets a Boolean preference and signals its new value.
 * @param {string} name Preference name.
 * @param {boolean} value New preference value.
 * @param {boolean} commit Whether to commit the change to Chrome.
 * @param {string} metric User metrics identifier.
 */
Preferences.prototype.setBooleanPref = function(name, value, commit, metric) {
  if (!commit) {
    Preferences.getInstance().setPrefNoCommit_(name, 'bool', Boolean(value));
    return;
  }

  var argumentList = [name, Boolean(value)];
  if (metric != undefined) argumentList.push(metric);
  chrome.send('setBooleanPref', argumentList);
};

  /**
   * Sets an integer preference and signals its new value.
   * @param {string} name Preference name.
   * @param {number} value New preference value.
   * @param {boolean} commit Whether to commit the change to Chrome.
   * @param {string} metric User metrics identifier.
   */
  Preferences.prototype.setIntegerPref = function(name, value, commit, metric) {
    if (!commit) {
      Preferences.getInstance().setPrefNoCommit_(name, 'int', Number(value));
      return;
    }

    var argumentList = [name, Number(value)];
    if (metric != undefined) argumentList.push(metric);
    chrome.send('setIntegerPref', argumentList);
  };

  /**
   * Sets a double-valued preference and signals its new value.
   * @param {string} name Preference name.
   * @param {number} value New preference value.
   * @param {boolean} commit Whether to commit the change to Chrome.
   * @param {string} metric User metrics identifier.
   */
  Preferences.prototype.setDoublePref = function(name, value, commit, metric) {
    if (!commit) {
      Preferences.getInstance().setPrefNoCommit_(name, 'double', Number(value));
      return;
    }

    var argumentList = [name, Number(value)];
    if (metric != undefined) argumentList.push(metric);
    chrome.send('setDoublePref', argumentList);
  };

  /**
   * Sets a string preference and signals its new value.
   * @param {string} name Preference name.
   * @param {string} value New preference value.
   * @param {boolean} commit Whether to commit the change to Chrome.
   * @param {string} metric User metrics identifier.
   */
  Preferences.prototype.setStringPref = function(name, value, commit, metric) {
    if (!commit) {
      Preferences.getInstance().setPrefNoCommit_(name, 'string', String(value));
      return;
    }

    var argumentList = [name, String(value)];
    if (metric != undefined) argumentList.push(metric);
    chrome.send('setStringPref', argumentList);
  };

  /**
   * Sets a string preference that represents a URL and signals its new value.
   * The value will be fixed to be a valid URL when it gets committed to Chrome.
   * @param {string} name Preference name.
   * @param {string} value New preference value.
   * @param {boolean} commit Whether to commit the change to Chrome.
   * @param {string} metric User metrics identifier.
   */
  Preferences.prototype.setURLPref = function(name, value, commit, metric) {
    if (!commit) {
      Preferences.getInstance().setPrefNoCommit_(name, 'url', String(value));
      return;
    }

    var argumentList = [name, String(value)];
    if (metric != undefined) argumentList.push(metric);
    chrome.send('setURLPref', argumentList);
  };

  /**
   * Sets a JSON list preference and signals its new value.
   * @param {string} name Preference name.
   * @param {Array} value New preference value.
   * @param {boolean} commit Whether to commit the change to Chrome.
   * @param {string} metric User metrics identifier.
   */
  Preferences.prototype.setListPref = function(name, value, commit, metric) {
    if (!commit) {
      Preferences.getInstance().setPrefNoCommit_(name, 'list', value);
      return;
    }

    var argumentList = [name, JSON.stringify(value)];
    if (metric != undefined) argumentList.push(metric);
    chrome.send('setListPref', argumentList);
  };

  /**
   * Clears the user setting for a preference and signals its new effective
   * value.
   * @param {string} name Preference name.
   * @param {boolean} commit Whether to commit the change to Chrome.
   * @param {string} metric User metrics identifier.
   */
  Preferences.prototype.clearPref = function(name, commit, metric) {
    if (!commit) {
      Preferences.getInstance().clearPrefNoCommit_(name);
      return;
    }

    var argumentList = [name];
    if (metric != undefined) argumentList.push(metric);
    chrome.send('clearPref', argumentList);
  };
  
    /**
   * Clears the user setting for a preference and signals its new effective
   * value.
   * @param {string} name Preference name.
   * @param {boolean} commit Whether to commit the change to Chrome.
   * @param {string} metric User metrics identifier.
   */
  Preferences.prototype.fetchPrefs = function(prefnames, callbackname) {
    var params = [callbackname];
    
    for (var i=0; i<prefnames.length; i++){
      params.push(prefnames[i]);
    }
    chrome.send('fetchPrefs', params);
  };

  addSingletonGetter(Preferences);