/*
 * Copyright (C) 2013 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.
 */
/**
 * @implements {UI.ViewLocationResolver}
 * @unrestricted
 */
Settings.SettingsScreen = class extends UI.VBox {
  constructor() {
    super(true);
    this.registerRequiredCSS('settings/settingsScreen.css');

    this.contentElement.tabIndex = 0;
    this.contentElement.classList.add('help-window-main');
    this.contentElement.classList.add('vbox');

    var settingsLabelElement = createElement('div');
    UI.createShadowRootWithCoreStyles(settingsLabelElement, 'settings/settingsScreen.css')
        .createChild('div', 'settings-window-title')
        .textContent = Common.UIString('Settings');

    this._tabbedLocation =
        UI.viewManager.createTabbedLocation(() => Settings.SettingsScreen._showSettingsScreen(), 'settings-view');
    var tabbedPane = this._tabbedLocation.tabbedPane();
    tabbedPane.leftToolbar().appendToolbarItem(new UI.ToolbarItem(settingsLabelElement));
    tabbedPane.setShrinkableTabs(false);
    tabbedPane.setVerticalTabLayout(true);
    var shortcutsView = new UI.SimpleView(Common.UIString('Shortcuts'));
    UI.shortcutsScreen.createShortcutsTabView().show(shortcutsView.element);
    this._tabbedLocation.appendView(shortcutsView);
    tabbedPane.show(this.contentElement);

    this.element.addEventListener('keydown', this._keyDown.bind(this), false);
    this._developerModeCounter = 0;
    this.setDefaultFocusedElement(this.contentElement);
  }

  /**
   * @param {string=} name
   */
  static _showSettingsScreen(name) {
    var settingsScreen =
        /** @type {!Settings.SettingsScreen} */ (self.runtime.sharedInstance(Settings.SettingsScreen));
    if (settingsScreen.isShowing())
      return;
    var dialog = new UI.Dialog();
    dialog.addCloseButton();
    settingsScreen.show(dialog.contentElement);
    dialog.show();
    settingsScreen._selectTab(name || 'preferences');
  }

  /**
   * @override
   * @param {string} locationName
   * @return {?UI.ViewLocation}
   */
  resolveLocation(locationName) {
    return this._tabbedLocation;
  }

  /**
   * @param {string} name
   */
  _selectTab(name) {
    UI.viewManager.showView(name);
  }

  /**
   * @param {!Event} event
   */
  _keyDown(event) {
    var shiftKeyCode = 16;
    if (event.keyCode === shiftKeyCode && ++this._developerModeCounter > 5)
      this.contentElement.classList.add('settings-developer-mode');
  }
};


/**
 * @unrestricted
 */
Settings.SettingsTab = class extends UI.VBox {
  /**
   * @param {string} name
   * @param {string=} id
   */
  constructor(name, id) {
    super();
    this.element.classList.add('settings-tab-container');
    if (id)
      this.element.id = id;
    var header = this.element.createChild('header');
    header.createChild('h3').createTextChild(name);
    this.containerElement = this.element.createChild('div', 'help-container-wrapper')
                                .createChild('div', 'settings-tab help-content help-container');
  }

  /**
   *  @param {string=} name
   *  @return {!Element}
   */
  _appendSection(name) {
    var block = this.containerElement.createChild('div', 'help-block');
    if (name)
      block.createChild('div', 'help-section-title').textContent = name;
    return block;
  }

  _createSelectSetting(name, options, setting) {
    var p = createElement('p');
    p.createChild('label').textContent = name;

    var select = p.createChild('select', 'chrome-select');
    var settingValue = setting.get();

    for (var i = 0; i < options.length; ++i) {
      var option = options[i];
      select.add(new Option(option[0], option[1]));
      if (settingValue === option[1])
        select.selectedIndex = i;
    }

    function changeListener(e) {
      // Don't use e.target.value to avoid conversion of the value to string.
      setting.set(options[select.selectedIndex][1]);
    }

    select.addEventListener('change', changeListener, false);
    return p;
  }
};

/**
 * @unrestricted
 */
Settings.GenericSettingsTab = class extends Settings.SettingsTab {
  constructor() {
    super(Common.UIString('Preferences'), 'preferences-tab-content');

    /** @const */
    var explicitSectionOrder =
        ['', 'Appearance', 'Elements', 'Sources', 'Network', 'Profiler', 'Console', 'Extensions'];
    /** @type {!Map<string, !Element>} */
    this._nameToSection = new Map();
    /** @type {!Map<string, !Element>} */
    this._nameToSettingElement = new Map();
    for (var sectionName of explicitSectionOrder)
      this._sectionElement(sectionName);
    self.runtime.extensions('setting').forEach(this._addSetting.bind(this));
    self.runtime.extensions(UI.SettingUI).forEach(this._addSettingUI.bind(this));

    this._appendSection().appendChild(
        UI.createTextButton(Common.UIString('Restore defaults and reload'), restoreAndReload));

    function restoreAndReload() {
      Common.settings.clearAll();
      Components.reload();
    }
  }

  /**
   * @param {!Runtime.Extension} extension
   * @return {boolean}
   */
  static isSettingVisible(extension) {
    var descriptor = extension.descriptor();
    if (!('title' in descriptor))
      return false;
    if (!('category' in descriptor))
      return false;
    return true;
  }

  /**
   * @param {!Runtime.Extension} extension
   */
  _addSetting(extension) {
    if (!Settings.GenericSettingsTab.isSettingVisible(extension))
      return;
    var descriptor = extension.descriptor();
    var sectionName = descriptor['category'];
    var settingName = descriptor['settingName'];
    var setting = Common.moduleSetting(settingName);
    var uiTitle = Common.UIString(extension.title());

    var sectionElement = this._sectionElement(sectionName);
    var settingControl;

    switch (descriptor['settingType']) {
      case 'boolean':
        settingControl = UI.SettingsUI.createSettingCheckbox(uiTitle, setting);
        break;
      case 'enum':
        var descriptorOptions = descriptor['options'];
        var options = new Array(descriptorOptions.length);
        for (var i = 0; i < options.length; ++i) {
          // The "raw" flag indicates text is non-i18n-izable.
          var optionName = descriptorOptions[i]['raw'] ? descriptorOptions[i]['text'] :
                                                         Common.UIString(descriptorOptions[i]['text']);
          options[i] = [optionName, descriptorOptions[i]['value']];
        }
        settingControl = this._createSelectSetting(uiTitle, options, setting);
        break;
      default:
        console.error('Invalid setting type: ' + descriptor['settingType']);
        return;
    }
    this._nameToSettingElement.set(settingName, settingControl);
    sectionElement.appendChild(/** @type {!Element} */ (settingControl));
  }

  /**
   * @param {!Runtime.Extension} extension
   */
  _addSettingUI(extension) {
    var descriptor = extension.descriptor();
    var sectionName = descriptor['category'] || '';
    extension.instance().then(appendCustomSetting.bind(this));

    /**
     * @param {!Object} object
     * @this {Settings.GenericSettingsTab}
     */
    function appendCustomSetting(object) {
      var settingUI = /** @type {!UI.SettingUI} */ (object);
      var element = settingUI.settingElement();
      if (element)
        this._sectionElement(sectionName).appendChild(element);
    }
  }

  /**
   * @param {string} sectionName
   * @return {!Element}
   */
  _sectionElement(sectionName) {
    var sectionElement = this._nameToSection.get(sectionName);
    if (!sectionElement) {
      var uiSectionName = sectionName && Common.UIString(sectionName);
      sectionElement = this._appendSection(uiSectionName);
      this._nameToSection.set(sectionName, sectionElement);
    }
    return sectionElement;
  }
};


/**
 * @unrestricted
 */
Settings.WorkspaceSettingsTab = class extends Settings.SettingsTab {
  constructor() {
    super(Common.UIString('Workspace'), 'workspace-tab-content');
    Workspace.isolatedFileSystemManager.addEventListener(
        Workspace.IsolatedFileSystemManager.Events.FileSystemAdded, this._fileSystemAdded, this);
    Workspace.isolatedFileSystemManager.addEventListener(
        Workspace.IsolatedFileSystemManager.Events.FileSystemRemoved, this._fileSystemRemoved, this);

    var folderExcludePatternInput = this._createFolderExcludePatternInput();
    folderExcludePatternInput.classList.add('folder-exclude-pattern');
    this.containerElement.appendChild(folderExcludePatternInput);

    if (Runtime.experiments.isEnabled('persistence2')) {
      var div = this.containerElement.createChild('div', 'settings-info-message');
      div.createTextChild(Common.UIString('Mappings are inferred automatically. Please '));
      div.appendChild(UI.createExternalLink(
          'https://bugs.chromium.org/p/chromium/issues/entry?template=Defect%20report%20from%20user&components=Platform%3EDevTools%3EAuthoring&comment=DevTools%20failed%20to%20link%20network%20resource%20to%20filesystem.%0A%0APlatform%3A%20%3CLinux%2FWin%2FMac%3E%0AChrome%20version%3A%20%3Cyour%20chrome%20version%3E%0A%0AWhat%20are%20the%20details%20of%20your%20project%3F%0A-%20Source%20code%20(if%20any)%3A%20http%3A%2F%2Fgithub.com%2Fexample%2Fexample%0A-%20Build%20System%3A%20gulp%2Fgrunt%2Fwebpack%2Frollup%2F...%0A-%20HTTP%20server%3A%20node%20HTTP%2Fnginx%2Fapache...%0A%0AAssets%20failed%20to%20link%20(or%20incorrectly%20linked)%3A%0A1.%0A2.%0A3.%0A%0AIf%20possible%2C%20please%20attach%20a%20screenshot%20of%20network%20sources%20navigator%20which%20should%0Ashow%20which%20resources%20failed%20to%20map',
          Common.UIString('report')));
      div.createTextChild(Common.UIString(' any bugs.'));
    }

    this._fileSystemsListContainer = this.containerElement.createChild('div', '');

    this.containerElement.appendChild(
        UI.createTextButton(Common.UIString('Add folder\u2026'), this._addFileSystemClicked.bind(this)));

    /** @type {!Map<string, !Element>} */
    this._elementByPath = new Map();

    /** @type {!Map<string, !Settings.EditFileSystemView>} */
    this._mappingViewByPath = new Map();

    var fileSystems = Workspace.isolatedFileSystemManager.fileSystems();
    for (var i = 0; i < fileSystems.length; ++i)
      this._addItem(fileSystems[i]);
  }

  /**
   * @return {!Element}
   */
  _createFolderExcludePatternInput() {
    var p = createElement('p');
    var labelElement = p.createChild('label');
    labelElement.textContent = Common.UIString('Folder exclude pattern');
    var inputElement = p.createChild('input');
    inputElement.type = 'text';
    inputElement.style.width = '270px';
    var folderExcludeSetting = Workspace.isolatedFileSystemManager.workspaceFolderExcludePatternSetting();
    var setValue =
        UI.bindInput(inputElement, folderExcludeSetting.set.bind(folderExcludeSetting), regexValidator, false);
    folderExcludeSetting.addChangeListener(() => setValue.call(null, folderExcludeSetting.get()));
    setValue(folderExcludeSetting.get());
    return p;

    /**
     * @param {string} value
     * @return {boolean}
     */
    function regexValidator(value) {
      var regex;
      try {
        regex = new RegExp(value);
      } catch (e) {
      }
      return !!regex;
    }
  }

  /**
   * @param {!Workspace.IsolatedFileSystem} fileSystem
   */
  _addItem(fileSystem) {
    var element = this._renderFileSystem(fileSystem);
    this._elementByPath.set(fileSystem.path(), element);

    this._fileSystemsListContainer.appendChild(element);

    var mappingView = new Settings.EditFileSystemView(fileSystem.path());
    this._mappingViewByPath.set(fileSystem.path(), mappingView);
    mappingView.element.classList.add('file-system-mapping-view');
    mappingView.show(element);
  }

  /**
   * @param {!Workspace.IsolatedFileSystem} fileSystem
   * @return {!Element}
   */
  _renderFileSystem(fileSystem) {
    var fileSystemPath = fileSystem.path();
    var lastIndexOfSlash = fileSystemPath.lastIndexOf(Host.isWin() ? '\\' : '/');
    var folderName = fileSystemPath.substr(lastIndexOfSlash + 1);

    var element = createElementWithClass('div', 'file-system-container');
    var header = element.createChild('div', 'file-system-header');

    header.createChild('div', 'file-system-name').textContent = folderName;
    var path = header.createChild('div', 'file-system-path');
    path.textContent = fileSystemPath;
    path.title = fileSystemPath;

    var toolbar = new UI.Toolbar('');
    var button = new UI.ToolbarButton(Common.UIString('Remove'), 'largeicon-delete');
    button.addEventListener(UI.ToolbarButton.Events.Click, this._removeFileSystemClicked.bind(this, fileSystem));
    toolbar.appendToolbarItem(button);
    header.appendChild(toolbar.element);

    return element;
  }

  /**
   * @param {!Workspace.IsolatedFileSystem} fileSystem
   */
  _removeFileSystemClicked(fileSystem) {
    Workspace.isolatedFileSystemManager.removeFileSystem(fileSystem);
  }

  _addFileSystemClicked() {
    Workspace.isolatedFileSystemManager.addFileSystem();
  }

  _fileSystemAdded(event) {
    var fileSystem = /** @type {!Workspace.IsolatedFileSystem} */ (event.data);
    this._addItem(fileSystem);
  }

  _fileSystemRemoved(event) {
    var fileSystem = /** @type {!Workspace.IsolatedFileSystem} */ (event.data);

    var mappingView = this._mappingViewByPath.get(fileSystem.path());
    if (mappingView) {
      mappingView.dispose();
      this._mappingViewByPath.delete(fileSystem.path());
    }

    var element = this._elementByPath.get(fileSystem.path());
    if (element) {
      this._elementByPath.delete(fileSystem.path());
      element.remove();
    }
  }
};

/**
 * @unrestricted
 */
Settings.ExperimentsSettingsTab = class extends Settings.SettingsTab {
  constructor() {
    super(Common.UIString('Experiments'), 'experiments-tab-content');

    var experiments = Runtime.experiments.allConfigurableExperiments();
    if (experiments.length) {
      var experimentsSection = this._appendSection();
      experimentsSection.appendChild(this._createExperimentsWarningSubsection());
      for (var i = 0; i < experiments.length; ++i)
        experimentsSection.appendChild(this._createExperimentCheckbox(experiments[i]));
    }
  }

  /**
   * @return {!Element} element
   */
  _createExperimentsWarningSubsection() {
    var subsection = createElement('div');
    var warning = subsection.createChild('span', 'settings-experiments-warning-subsection-warning');
    warning.textContent = Common.UIString('WARNING:');
    subsection.createTextChild(' ');
    var message = subsection.createChild('span', 'settings-experiments-warning-subsection-message');
    message.textContent = Common.UIString('These experiments could be dangerous and may require restart.');
    return subsection;
  }

  _createExperimentCheckbox(experiment) {
    var label = UI.createCheckboxLabel(Common.UIString(experiment.title), experiment.isEnabled());
    var input = label.checkboxElement;
    input.name = experiment.name;
    function listener() {
      experiment.setEnabled(input.checked);
    }
    input.addEventListener('click', listener, false);

    var p = createElement('p');
    p.className = experiment.hidden && !experiment.isEnabled() ? 'settings-experiment-hidden' : '';
    p.appendChild(label);
    return p;
  }
};

/**
 * @implements {UI.ActionDelegate}
 * @unrestricted
 */
Settings.SettingsScreen.ActionDelegate = class {
  /**
   * @override
   * @param {!UI.Context} context
   * @param {string} actionId
   * @return {boolean}
   */
  handleAction(context, actionId) {
    switch (actionId) {
      case 'settings.show':
        Settings.SettingsScreen._showSettingsScreen();
        return true;
      case 'settings.documentation':
        InspectorFrontendHost.openInNewTab('https://developers.google.com/web/tools/chrome-devtools/');
        return true;
      case 'settings.shortcuts':
        Settings.SettingsScreen._showSettingsScreen(Common.UIString('Shortcuts'));
        return true;
    }
    return false;
  }
};

/**
 * @implements {Common.Revealer}
 * @unrestricted
 */
Settings.SettingsScreen.Revealer = class {
  /**
   * @override
   * @param {!Object} object
   * @return {!Promise}
   */
  reveal(object) {
    console.assert(object instanceof Common.Setting);
    var setting = /** @type {!Common.Setting} */ (object);
    var success = false;

    self.runtime.extensions('setting').forEach(revealModuleSetting);
    self.runtime.extensions(UI.SettingUI).forEach(revealSettingUI);
    self.runtime.extensions('view').forEach(revealSettingsView);

    return success ? Promise.resolve() : Promise.reject();

    /**
     * @param {!Runtime.Extension} extension
     */
    function revealModuleSetting(extension) {
      if (!Settings.GenericSettingsTab.isSettingVisible(extension))
        return;
      if (extension.descriptor()['settingName'] === setting.name) {
        InspectorFrontendHost.bringToFront();
        Settings.SettingsScreen._showSettingsScreen();
        success = true;
      }
    }

    /**
     * @param {!Runtime.Extension} extension
     */
    function revealSettingUI(extension) {
      var settings = extension.descriptor()['settings'];
      if (settings && settings.indexOf(setting.name) !== -1) {
        InspectorFrontendHost.bringToFront();
        Settings.SettingsScreen._showSettingsScreen();
        success = true;
      }
    }

    /**
     * @param {!Runtime.Extension} extension
     */
    function revealSettingsView(extension) {
      var location = extension.descriptor()['location'];
      if (location !== 'settings-view')
        return;
      var settings = extension.descriptor()['settings'];
      if (settings && settings.indexOf(setting.name) !== -1) {
        InspectorFrontendHost.bringToFront();
        Settings.SettingsScreen._showSettingsScreen(extension.descriptor()['id']);
        success = true;
      }
    }
  }
};
