/*
 * Copyright (C) 2009 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import {ObjectWrapper} from './Object.js';

/**
 * @unrestricted
 */
export class Settings {
  /**
   * @param {!SettingsStorage} globalStorage
   * @param {!SettingsStorage} localStorage
   */
  constructor(globalStorage, localStorage) {
    this._globalStorage = globalStorage;
    this._localStorage = localStorage;
    this._sessionStorage = new SettingsStorage({});

    this._eventSupport = new ObjectWrapper();
    /** @type {!Map<string, !Setting>} */
    this._registry = new Map();
    /** @type {!Map<string, !Setting>} */
    this._moduleSettings = new Map();
    self.runtime.extensions('setting').forEach(this._registerModuleSetting.bind(this));
  }

  /**
   * @param {!Root.Runtime.Extension} extension
   */
  _registerModuleSetting(extension) {
    const descriptor = extension.descriptor();
    const settingName = descriptor['settingName'];
    const isRegex = descriptor['settingType'] === 'regex';
    const defaultValue = descriptor['defaultValue'];
    let storageType;
    switch (descriptor['storageType']) {
      case ('local'):
        storageType = SettingStorageType.Local;
        break;
      case ('session'):
        storageType = SettingStorageType.Session;
        break;
      case ('global'):
        storageType = SettingStorageType.Global;
        break;
      default:
        storageType = SettingStorageType.Global;
    }
    const setting = isRegex ? this.createRegExpSetting(settingName, defaultValue, undefined, storageType) :
                              this.createSetting(settingName, defaultValue, storageType);
    if (extension.title()) {
      setting.setTitle(extension.title());
    }
    if (descriptor['userActionCondition']) {
      setting.setRequiresUserAction(!!Root.Runtime.queryParam(descriptor['userActionCondition']));
    }
    setting._extension = extension;
    this._moduleSettings.set(settingName, setting);
  }

  /**
   * @param {string} settingName
   * @return {!Setting}
   */
  moduleSetting(settingName) {
    const setting = this._moduleSettings.get(settingName);
    if (!setting) {
      throw new Error('No setting registered: ' + settingName);
    }
    return setting;
  }

  /**
   * @param {string} settingName
   * @return {!Setting}
   */
  settingForTest(settingName) {
    const setting = this._registry.get(settingName);
    if (!setting) {
      throw new Error('No setting registered: ' + settingName);
    }
    return setting;
  }

  /**
   * @param {string} key
   * @param {*} defaultValue
   * @param {!SettingStorageType=} storageType
   * @return {!Setting}
   */
  createSetting(key, defaultValue, storageType) {
    const storage = this._storageFromType(storageType);
    if (!this._registry.get(key)) {
      this._registry.set(key, new Setting(this, key, defaultValue, this._eventSupport, storage));
    }
    return /** @type {!Setting} */ (this._registry.get(key));
  }

  /**
   * @param {string} key
   * @param {*} defaultValue
   * @return {!Setting}
   */
  createLocalSetting(key, defaultValue) {
    return this.createSetting(key, defaultValue, SettingStorageType.Local);
  }

  /**
   * @param {string} key
   * @param {string} defaultValue
   * @param {string=} regexFlags
   * @param {!SettingStorageType=} storageType
   * @return {!RegExpSetting}
   */
  createRegExpSetting(key, defaultValue, regexFlags, storageType) {
    if (!this._registry.get(key)) {
      this._registry.set(
          key,
          new RegExpSetting(
              this, key, defaultValue, this._eventSupport, this._storageFromType(storageType), regexFlags));
    }
    return /** @type {!RegExpSetting} */ (this._registry.get(key));
  }

  clearAll() {
    this._globalStorage.removeAll();
    this._localStorage.removeAll();
    const versionSetting = Common.settings.createSetting(VersionController._currentVersionName, 0);
    versionSetting.set(VersionController.currentVersion);
  }

  /**
   * @param {!SettingStorageType=} storageType
   * @return {!SettingsStorage}
   */
  _storageFromType(storageType) {
    switch (storageType) {
      case (SettingStorageType.Local):
        return this._localStorage;
      case (SettingStorageType.Session):
        return this._sessionStorage;
      case (SettingStorageType.Global):
        return this._globalStorage;
    }
    return this._globalStorage;
  }
}

/**
 * @unrestricted
 */
export class SettingsStorage {
  /**
   * @param {!Object} object
   * @param {function(string, string)=} setCallback
   * @param {function(string)=} removeCallback
   * @param {function(string)=} removeAllCallback
   * @param {string=} storagePrefix
   */
  constructor(object, setCallback, removeCallback, removeAllCallback, storagePrefix) {
    this._object = object;
    this._setCallback = setCallback || function() {};
    this._removeCallback = removeCallback || function() {};
    this._removeAllCallback = removeAllCallback || function() {};
    this._storagePrefix = storagePrefix || '';
  }

  /**
   * @param {string} name
   * @param {string} value
   */
  set(name, value) {
    name = this._storagePrefix + name;
    this._object[name] = value;
    this._setCallback(name, value);
  }

  /**
   * @param {string} name
   * @return {boolean}
   */
  has(name) {
    name = this._storagePrefix + name;
    return name in this._object;
  }

  /**
   * @param {string} name
   * @return {string}
   */
  get(name) {
    name = this._storagePrefix + name;
    return this._object[name];
  }

  /**
   * @param {string} name
   */
  remove(name) {
    name = this._storagePrefix + name;
    delete this._object[name];
    this._removeCallback(name);
  }

  removeAll() {
    this._object = {};
    this._removeAllCallback();
  }

  _dumpSizes() {
    Common.console.log('Ten largest settings: ');

    const sizes = {__proto__: null};
    for (const key in this._object) {
      sizes[key] = this._object[key].length;
    }
    const keys = Object.keys(sizes);

    function comparator(key1, key2) {
      return sizes[key2] - sizes[key1];
    }

    keys.sort(comparator);

    for (let i = 0; i < 10 && i < keys.length; ++i) {
      Common.console.log('Setting: \'' + keys[i] + '\', size: ' + sizes[keys[i]]);
    }
  }
}

/**
 * @template V
 * @unrestricted
 */
export class Setting {
  /**
   * @param {!Settings} settings
   * @param {string} name
   * @param {V} defaultValue
   * @param {!ObjectWrapper} eventSupport
   * @param {!SettingsStorage} storage
   */
  constructor(settings, name, defaultValue, eventSupport, storage) {
    this._settings = settings;
    this._name = name;
    this._defaultValue = defaultValue;
    this._eventSupport = eventSupport;
    this._storage = storage;
    /** @type {string} */
    this._title = '';
    this._extension = null;
  }

  /**
   * @param {function(!Common.Event)} listener
   * @param {!Object=} thisObject
   * @return {!Common.EventTarget.EventDescriptor}
   */
  addChangeListener(listener, thisObject) {
    return this._eventSupport.addEventListener(this._name, listener, thisObject);
  }

  /**
   * @param {function(!Common.Event)} listener
   * @param {!Object=} thisObject
   */
  removeChangeListener(listener, thisObject) {
    this._eventSupport.removeEventListener(this._name, listener, thisObject);
  }

  get name() {
    return this._name;
  }

  /**
   * @return {string}
   */
  title() {
    return this._title;
  }

  /**
   * @param {string} title
   */
  setTitle(title) {
    this._title = title;
  }

  /**
   * @param {boolean} requiresUserAction
   */
  setRequiresUserAction(requiresUserAction) {
    this._requiresUserAction = requiresUserAction;
  }

  /**
   * @return {V}
   */
  get() {
    if (this._requiresUserAction && !this._hadUserAction) {
      return this._defaultValue;
    }

    if (typeof this._value !== 'undefined') {
      return this._value;
    }

    this._value = this._defaultValue;
    if (this._storage.has(this._name)) {
      try {
        this._value = JSON.parse(this._storage.get(this._name));
      } catch (e) {
        this._storage.remove(this._name);
      }
    }
    return this._value;
  }

  /**
   * @param {V} value
   */
  set(value) {
    this._hadUserAction = true;
    this._value = value;
    try {
      const settingString = JSON.stringify(value);
      try {
        this._storage.set(this._name, settingString);
      } catch (e) {
        this._printSettingsSavingError(e.message, this._name, settingString);
      }
    } catch (e) {
      Common.console.error('Cannot stringify setting with name: ' + this._name + ', error: ' + e.message);
    }
    this._eventSupport.dispatchEventToListeners(this._name, value);
  }

  remove() {
    this._settings._registry.delete(this._name);
    this._settings._moduleSettings.delete(this._name);
    this._storage.remove(this._name);
  }

  /**
   * @return {?Root.Runtime.Extension}
   */
  extension() {
    return this._extension;
  }

  /**
   * @param {string} message
   * @param {string} name
   * @param {string} value
   */
  _printSettingsSavingError(message, name, value) {
    const errorMessage =
        'Error saving setting with name: ' + this._name + ', value length: ' + value.length + '. Error: ' + message;
    console.error(errorMessage);
    Common.console.error(errorMessage);
    this._storage._dumpSizes();
  }
}

/**
 * @unrestricted
 */
export class RegExpSetting extends Setting {
  /**
   * @param {!Settings} settings
   * @param {string} name
   * @param {string} defaultValue
   * @param {!ObjectWrapper} eventSupport
   * @param {!SettingsStorage} storage
   * @param {string=} regexFlags
   */
  constructor(settings, name, defaultValue, eventSupport, storage, regexFlags) {
    super(settings, name, defaultValue ? [{pattern: defaultValue}] : [], eventSupport, storage);
    this._regexFlags = regexFlags;
  }

  /**
   * @override
   * @return {string}
   */
  get() {
    const result = [];
    const items = this.getAsArray();
    for (let i = 0; i < items.length; ++i) {
      const item = items[i];
      if (item.pattern && !item.disabled) {
        result.push(item.pattern);
      }
    }
    return result.join('|');
  }

  /**
   * @return {!Array.<{pattern: string, disabled: (boolean|undefined)}>}
   */
  getAsArray() {
    return super.get();
  }

  /**
   * @override
   * @param {string} value
   */
  set(value) {
    this.setAsArray([{pattern: value}]);
  }

  /**
   * @param {!Array.<{pattern: string, disabled: (boolean|undefined)}>} value
   */
  setAsArray(value) {
    delete this._regex;
    super.set(value);
  }

  /**
   * @return {?RegExp}
   */
  asRegExp() {
    if (typeof this._regex !== 'undefined') {
      return this._regex;
    }
    this._regex = null;
    try {
      const pattern = this.get();
      if (pattern) {
        this._regex = new RegExp(pattern, this._regexFlags || '');
      }
    } catch (e) {
    }
    return this._regex;
  }
}

/**
 * @unrestricted
 */
export class VersionController {
  static get _currentVersionName() {
    return 'inspectorVersion';
  }

  static get currentVersion() {
    return 28;
  }

  updateVersion() {
    const localStorageVersion = window.localStorage ? window.localStorage[VersionController._currentVersionName] : 0;
    const versionSetting = Common.settings.createSetting(VersionController._currentVersionName, 0);
    const currentVersion = VersionController.currentVersion;
    const oldVersion = versionSetting.get() || parseInt(localStorageVersion || '0', 10);
    if (oldVersion === 0) {
      // First run, no need to do anything.
      versionSetting.set(currentVersion);
      return;
    }
    const methodsToRun = this._methodsToRunToUpdateVersion(oldVersion, currentVersion);
    for (let i = 0; i < methodsToRun.length; ++i) {
      this[methodsToRun[i]].call(this);
    }
    versionSetting.set(currentVersion);
  }

  /**
   * @param {number} oldVersion
   * @param {number} currentVersion
   */
  _methodsToRunToUpdateVersion(oldVersion, currentVersion) {
    const result = [];
    for (let i = oldVersion; i < currentVersion; ++i) {
      result.push('_updateVersionFrom' + i + 'To' + (i + 1));
    }
    return result;
  }

  _updateVersionFrom0To1() {
    this._clearBreakpointsWhenTooMany(Common.settings.createLocalSetting('breakpoints', []), 500000);
  }

  _updateVersionFrom1To2() {
    Common.settings.createSetting('previouslyViewedFiles', []).set([]);
  }

  _updateVersionFrom2To3() {
    Common.settings.createSetting('fileSystemMapping', {}).set({});
    Common.settings.createSetting('fileMappingEntries', []).remove();
  }

  _updateVersionFrom3To4() {
    const advancedMode = Common.settings.createSetting('showHeaSnapshotObjectsHiddenProperties', false);
    moduleSetting('showAdvancedHeapSnapshotProperties').set(advancedMode.get());
    advancedMode.remove();
  }

  _updateVersionFrom4To5() {
    const settingNames = {
      'FileSystemViewSidebarWidth': 'fileSystemViewSplitViewState',
      'elementsSidebarWidth': 'elementsPanelSplitViewState',
      'StylesPaneSplitRatio': 'stylesPaneSplitViewState',
      'heapSnapshotRetainersViewSize': 'heapSnapshotSplitViewState',
      'InspectorView.splitView': 'InspectorView.splitViewState',
      'InspectorView.screencastSplitView': 'InspectorView.screencastSplitViewState',
      'Inspector.drawerSplitView': 'Inspector.drawerSplitViewState',
      'layerDetailsSplitView': 'layerDetailsSplitViewState',
      'networkSidebarWidth': 'networkPanelSplitViewState',
      'sourcesSidebarWidth': 'sourcesPanelSplitViewState',
      'scriptsPanelNavigatorSidebarWidth': 'sourcesPanelNavigatorSplitViewState',
      'sourcesPanelSplitSidebarRatio': 'sourcesPanelDebuggerSidebarSplitViewState',
      'timeline-details': 'timelinePanelDetailsSplitViewState',
      'timeline-split': 'timelinePanelRecorsSplitViewState',
      'timeline-view': 'timelinePanelTimelineStackSplitViewState',
      'auditsSidebarWidth': 'auditsPanelSplitViewState',
      'layersSidebarWidth': 'layersPanelSplitViewState',
      'profilesSidebarWidth': 'profilesPanelSplitViewState',
      'resourcesSidebarWidth': 'resourcesPanelSplitViewState'
    };
    const empty = {};
    for (const oldName in settingNames) {
      const newName = settingNames[oldName];
      const oldNameH = oldName + 'H';

      let newValue = null;
      const oldSetting = Common.settings.createSetting(oldName, empty);
      if (oldSetting.get() !== empty) {
        newValue = newValue || {};
        newValue.vertical = {};
        newValue.vertical.size = oldSetting.get();
        oldSetting.remove();
      }
      const oldSettingH = Common.settings.createSetting(oldNameH, empty);
      if (oldSettingH.get() !== empty) {
        newValue = newValue || {};
        newValue.horizontal = {};
        newValue.horizontal.size = oldSettingH.get();
        oldSettingH.remove();
      }
      if (newValue) {
        Common.settings.createSetting(newName, {}).set(newValue);
      }
    }
  }

  _updateVersionFrom5To6() {
    const settingNames = {
      'debuggerSidebarHidden': 'sourcesPanelSplitViewState',
      'navigatorHidden': 'sourcesPanelNavigatorSplitViewState',
      'WebInspector.Drawer.showOnLoad': 'Inspector.drawerSplitViewState'
    };

    for (const oldName in settingNames) {
      const oldSetting = Common.settings.createSetting(oldName, null);
      if (oldSetting.get() === null) {
        oldSetting.remove();
        continue;
      }

      const newName = settingNames[oldName];
      const invert = oldName === 'WebInspector.Drawer.showOnLoad';
      const hidden = oldSetting.get() !== invert;
      oldSetting.remove();
      const showMode = hidden ? 'OnlyMain' : 'Both';

      const newSetting = Common.settings.createSetting(newName, {});
      const newValue = newSetting.get() || {};
      newValue.vertical = newValue.vertical || {};
      newValue.vertical.showMode = showMode;
      newValue.horizontal = newValue.horizontal || {};
      newValue.horizontal.showMode = showMode;
      newSetting.set(newValue);
    }
  }

  _updateVersionFrom6To7() {
    const settingNames = {
      'sourcesPanelNavigatorSplitViewState': 'sourcesPanelNavigatorSplitViewState',
      'elementsPanelSplitViewState': 'elementsPanelSplitViewState',
      'stylesPaneSplitViewState': 'stylesPaneSplitViewState',
      'sourcesPanelDebuggerSidebarSplitViewState': 'sourcesPanelDebuggerSidebarSplitViewState'
    };

    const empty = {};
    for (const name in settingNames) {
      const setting = Common.settings.createSetting(name, empty);
      const value = setting.get();
      if (value === empty) {
        continue;
      }
      // Zero out saved percentage sizes, and they will be restored to defaults.
      if (value.vertical && value.vertical.size && value.vertical.size < 1) {
        value.vertical.size = 0;
      }
      if (value.horizontal && value.horizontal.size && value.horizontal.size < 1) {
        value.horizontal.size = 0;
      }
      setting.set(value);
    }
  }

  _updateVersionFrom7To8() {
  }

  _updateVersionFrom8To9() {
    const settingNames = ['skipStackFramesPattern', 'workspaceFolderExcludePattern'];

    for (let i = 0; i < settingNames.length; ++i) {
      const setting = Common.settings.createSetting(settingNames[i], '');
      let value = setting.get();
      if (!value) {
        return;
      }
      if (typeof value === 'string') {
        value = [value];
      }
      for (let j = 0; j < value.length; ++j) {
        if (typeof value[j] === 'string') {
          value[j] = {pattern: value[j]};
        }
      }
      setting.set(value);
    }
  }

  _updateVersionFrom9To10() {
    // This one is localStorage specific, which is fine.
    if (!window.localStorage) {
      return;
    }
    for (const key in window.localStorage) {
      if (key.startsWith('revision-history')) {
        window.localStorage.removeItem(key);
      }
    }
  }

  _updateVersionFrom10To11() {
    const oldSettingName = 'customDevicePresets';
    const newSettingName = 'customEmulatedDeviceList';
    const oldSetting = Common.settings.createSetting(oldSettingName, undefined);
    const list = oldSetting.get();
    if (!Array.isArray(list)) {
      return;
    }
    const newList = [];
    for (let i = 0; i < list.length; ++i) {
      const value = list[i];
      const device = {};
      device['title'] = value['title'];
      device['type'] = 'unknown';
      device['user-agent'] = value['userAgent'];
      device['capabilities'] = [];
      if (value['touch']) {
        device['capabilities'].push('touch');
      }
      if (value['mobile']) {
        device['capabilities'].push('mobile');
      }
      device['screen'] = {};
      device['screen']['vertical'] = {width: value['width'], height: value['height']};
      device['screen']['horizontal'] = {width: value['height'], height: value['width']};
      device['screen']['device-pixel-ratio'] = value['deviceScaleFactor'];
      device['modes'] = [];
      device['show-by-default'] = true;
      device['show'] = 'Default';
      newList.push(device);
    }
    if (newList.length) {
      Common.settings.createSetting(newSettingName, []).set(newList);
    }
    oldSetting.remove();
  }

  _updateVersionFrom11To12() {
    this._migrateSettingsFromLocalStorage();
  }

  _updateVersionFrom12To13() {
    this._migrateSettingsFromLocalStorage();
    Common.settings.createSetting('timelineOverviewMode', '').remove();
  }

  _updateVersionFrom13To14() {
    const defaultValue = {'throughput': -1, 'latency': 0};
    Common.settings.createSetting('networkConditions', defaultValue).set(defaultValue);
  }

  _updateVersionFrom14To15() {
    const setting = Common.settings.createLocalSetting('workspaceExcludedFolders', {});
    const oldValue = setting.get();
    const newValue = {};
    for (const fileSystemPath in oldValue) {
      newValue[fileSystemPath] = [];
      for (const entry of oldValue[fileSystemPath]) {
        newValue[fileSystemPath].push(entry.path);
      }
    }
    setting.set(newValue);
  }

  _updateVersionFrom15To16() {
    const setting = Common.settings.createSetting('InspectorView.panelOrder', {});
    const tabOrders = setting.get();
    for (const key of Object.keys(tabOrders)) {
      tabOrders[key] = (tabOrders[key] + 1) * 10;
    }
    setting.set(tabOrders);
  }

  _updateVersionFrom16To17() {
    const setting = Common.settings.createSetting('networkConditionsCustomProfiles', []);
    const oldValue = setting.get();
    const newValue = [];
    if (Array.isArray(oldValue)) {
      for (const preset of oldValue) {
        if (typeof preset.title === 'string' && typeof preset.value === 'object' &&
            typeof preset.value.throughput === 'number' && typeof preset.value.latency === 'number') {
          newValue.push({
            title: preset.title,
            value:
                {download: preset.value.throughput, upload: preset.value.throughput, latency: preset.value.latency}
          });
        }
      }
    }
    setting.set(newValue);
  }

  _updateVersionFrom17To18() {
    const setting = Common.settings.createLocalSetting('workspaceExcludedFolders', {});
    const oldValue = setting.get();
    const newValue = {};
    for (const oldKey in oldValue) {
      let newKey = oldKey.replace(/\\/g, '/');
      if (!newKey.startsWith('file://')) {
        if (newKey.startsWith('/')) {
          newKey = 'file://' + newKey;
        } else {
          newKey = 'file:///' + newKey;
        }
      }
      newValue[newKey] = oldValue[oldKey];
    }
    setting.set(newValue);
  }

  _updateVersionFrom18To19() {
    const defaultColumns = {status: true, type: true, initiator: true, size: true, time: true};
    const visibleColumnSettings = Common.settings.createSetting('networkLogColumnsVisibility', defaultColumns);
    const visibleColumns = visibleColumnSettings.get();
    visibleColumns.name = true;
    visibleColumns.timeline = true;

    const configs = {};
    for (const columnId in visibleColumns) {
      if (!visibleColumns.hasOwnProperty(columnId)) {
        continue;
      }
      configs[columnId.toLowerCase()] = {visible: visibleColumns[columnId]};
    }
    const newSetting = Common.settings.createSetting('networkLogColumns', {});
    newSetting.set(configs);
    visibleColumnSettings.remove();
  }

  _updateVersionFrom19To20() {
    const oldSetting = Common.settings.createSetting('InspectorView.panelOrder', {});
    const newSetting = Common.settings.createSetting('panel-tabOrder', {});
    newSetting.set(oldSetting.get());
    oldSetting.remove();
  }

  _updateVersionFrom20To21() {
    const networkColumns = Common.settings.createSetting('networkLogColumns', {});
    const columns = /** @type {!Object} */ (networkColumns.get());
    delete columns['timeline'];
    delete columns['waterfall'];
    networkColumns.set(columns);
  }

  _updateVersionFrom21To22() {
    const breakpointsSetting = Common.settings.createLocalSetting('breakpoints', []);
    const breakpoints = breakpointsSetting.get();
    for (const breakpoint of breakpoints) {
      breakpoint['url'] = breakpoint['sourceFileId'];
      delete breakpoint['sourceFileId'];
    }
    breakpointsSetting.set(breakpoints);
  }

  _updateVersionFrom22To23() {
    // This update is no-op.
  }

  _updateVersionFrom23To24() {
    const oldSetting = Common.settings.createSetting('searchInContentScripts', false);
    const newSetting = Common.settings.createSetting('searchInAnonymousAndContentScripts', false);
    newSetting.set(oldSetting.get());
    oldSetting.remove();
  }

  _updateVersionFrom24To25() {
    const defaultColumns = {status: true, type: true, initiator: true, size: true, time: true};
    const networkLogColumnsSetting = Common.settings.createSetting('networkLogColumns', defaultColumns);
    const columns = networkLogColumnsSetting.get();
    delete columns.product;
    networkLogColumnsSetting.set(columns);
  }

  _updateVersionFrom25To26() {
    const oldSetting = Common.settings.createSetting('messageURLFilters', {});
    const urls = Object.keys(oldSetting.get());
    const textFilter = urls.map(url => `-url:${url}`).join(' ');
    if (textFilter) {
      const textFilterSetting = Common.settings.createSetting('console.textFilter', '');
      const suffix = textFilterSetting.get() ? ` ${textFilterSetting.get()}` : '';
      textFilterSetting.set(`${textFilter}${suffix}`);
    }
    oldSetting.remove();
  }

  _updateVersionFrom26To27() {
    /**
     * @param {string} settingName
     * @param {string} from
     * @param {string} to
     */
    function renameKeyInObjectSetting(settingName, from, to) {
      const setting = Common.settings.createSetting(settingName, {});
      const value = setting.get();
      if (from in value) {
        value[to] = value[from];
        delete value[from];
        setting.set(value);
      }
    }

    /**
     * @param {string} settingName
     * @param {string} from
     * @param {string} to
     */
    function renameInStringSetting(settingName, from, to) {
      const setting = Common.settings.createSetting(settingName, '');
      const value = setting.get();
      if (value === from) {
        setting.set(to);
      }
    }

    renameKeyInObjectSetting('panel-tabOrder', 'audits2', 'audits');
    renameKeyInObjectSetting('panel-closeableTabs', 'audits2', 'audits');
    renameInStringSetting('panel-selectedTab', 'audits2', 'audits');
  }

  _updateVersionFrom27To28() {
    const setting = Common.settings.createSetting('uiTheme', 'systemPreferred');
    if (setting.get() === 'default') {
      setting.set('systemPreferred');
    }
  }

  _migrateSettingsFromLocalStorage() {
    // This step migrates all the settings except for the ones below into the browser profile.
    const localSettings = new Set([
      'advancedSearchConfig', 'breakpoints', 'consoleHistory', 'domBreakpoints', 'eventListenerBreakpoints',
      'fileSystemMapping', 'lastSelectedSourcesSidebarPaneTab', 'previouslyViewedFiles', 'savedURLs',
      'watchExpressions', 'workspaceExcludedFolders', 'xhrBreakpoints'
    ]);
    if (!window.localStorage) {
      return;
    }

    for (const key in window.localStorage) {
      if (localSettings.has(key)) {
        continue;
      }
      const value = window.localStorage[key];
      window.localStorage.removeItem(key);
      Common.settings._globalStorage[key] = value;
    }
  }

  /**
   * @param {!Setting} breakpointsSetting
   * @param {number} maxBreakpointsCount
   */
  _clearBreakpointsWhenTooMany(breakpointsSetting, maxBreakpointsCount) {
    // If there are too many breakpoints in a storage, it is likely due to a recent bug that caused
    // periodical breakpoints duplication leading to inspector slowness.
    if (breakpointsSetting.get().length > maxBreakpointsCount) {
      breakpointsSetting.set([]);
    }
  }
}

/**
 * @enum {symbol}
 */
export const SettingStorageType = {
  Global: Symbol('Global'),
  Local: Symbol('Local'),
  Session: Symbol('Session')
};

/**
 * @param {string} settingName
 * @return {!Setting}
 */
export function moduleSetting(settingName) {
  return Common.settings.moduleSetting(settingName);
}

/**
 * @param {string} settingName
 * @return {!Setting}
 */
export function settingForTest(settingName) {
  return Common.settings.settingForTest(settingName);
}
