/*
 * Copyright (C) 2011 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:
 *
 * 1. Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * 2. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. AND ITS 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 GOOGLE INC.
 * OR ITS 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.
 */

/**
 * @unrestricted
 */
Sources.NetworkNavigatorView = class extends Sources.NavigatorView {
  constructor() {
    super();
    SDK.targetManager.addEventListener(SDK.TargetManager.Events.InspectedURLChanged, this._inspectedURLChanged, this);

    // Record the sources tool load time after the file navigator has loaded.
    Host.userMetrics.panelLoaded('sources', 'DevTools.Launch.Sources');
  }

  /**
   * @override
   * @param {!Workspace.Project} project
   * @return {boolean}
   */
  acceptProject(project) {
    return project.type() === Workspace.projectTypes.Network;
  }

  /**
   * @param {!Common.Event} event
   */
  _inspectedURLChanged(event) {
    const mainTarget = SDK.targetManager.mainTarget();
    if (event.data !== mainTarget) {
      return;
    }
    const inspectedURL = mainTarget && mainTarget.inspectedURL();
    if (!inspectedURL) {
      return;
    }
    for (const uiSourceCode of this.workspace().uiSourceCodes()) {
      if (this.acceptProject(uiSourceCode.project()) && uiSourceCode.url() === inspectedURL) {
        this.revealUISourceCode(uiSourceCode, true);
      }
    }
  }

  /**
   * @override
   * @param {!Workspace.UISourceCode} uiSourceCode
   */
  uiSourceCodeAdded(uiSourceCode) {
    const mainTarget = SDK.targetManager.mainTarget();
    const inspectedURL = mainTarget && mainTarget.inspectedURL();
    if (!inspectedURL) {
      return;
    }
    if (uiSourceCode.url() === inspectedURL) {
      this.revealUISourceCode(uiSourceCode, true);
    }
  }
};

/**
 * @unrestricted
 */
Sources.FilesNavigatorView = class extends Sources.NavigatorView {
  constructor() {
    super();
    const placeholder = new UI.EmptyWidget('');
    this.setPlaceholder(placeholder);
    placeholder.appendParagraph().appendChild(UI.html`
      <div>${ls`Sync changes in DevTools with the local filesystem`}</div><br />
      ${UI.XLink.create('https://developers.google.com/web/tools/chrome-devtools/workspaces/', ls`Learn more`)}
    `);

    const toolbar = new UI.Toolbar('navigator-toolbar');
    toolbar.appendItemsAtLocation('files-navigator-toolbar').then(() => {
      if (!toolbar.empty()) {
        this.contentElement.insertBefore(toolbar.element, this.contentElement.firstChild);
      }
    });
  }

  /**
   * @override
   * @param {!Workspace.Project} project
   * @return {boolean}
   */
  acceptProject(project) {
    return project.type() === Workspace.projectTypes.FileSystem &&
        Persistence.FileSystemWorkspaceBinding.fileSystemType(project) !== 'overrides' &&
        !Snippets.isSnippetsProject(project);
  }

  /**
   * @override
   * @param {!Event} event
   */
  handleContextMenu(event) {
    const contextMenu = new UI.ContextMenu(event);
    contextMenu.defaultSection().appendAction('sources.add-folder-to-workspace', undefined, true);
    contextMenu.show();
  }
};

Sources.OverridesNavigatorView = class extends Sources.NavigatorView {
  constructor() {
    super();
    const placeholder = new UI.EmptyWidget('');
    this.setPlaceholder(placeholder);
    placeholder.appendParagraph().appendChild(UI.html`
      <div>${ls`Override page assets with files from a local folder`}</div><br />
      ${UI.XLink.create('https://developers.google.com/web/updates/2018/01/devtools#overrides', ls`Learn more`)}
    `);

    this._toolbar = new UI.Toolbar('navigator-toolbar');

    this.contentElement.insertBefore(this._toolbar.element, this.contentElement.firstChild);

    Persistence.networkPersistenceManager.addEventListener(
        Persistence.NetworkPersistenceManager.Events.ProjectChanged, this._updateProjectAndUI, this);
    this.workspace().addEventListener(Workspace.Workspace.Events.ProjectAdded, this._onProjectAddOrRemoved, this);
    this.workspace().addEventListener(Workspace.Workspace.Events.ProjectRemoved, this._onProjectAddOrRemoved, this);
    this._updateProjectAndUI();
  }

  /**
   * @param {!Common.Event} event
   */
  _onProjectAddOrRemoved(event) {
    const project = /** @type {!Workspace.Project} */ (event.data);
    if (project && project.type() === Workspace.projectTypes.FileSystem &&
        Persistence.FileSystemWorkspaceBinding.fileSystemType(project) !== 'overrides') {
      return;
    }
    this._updateUI();
  }

  _updateProjectAndUI() {
    this.reset();
    const project = Persistence.networkPersistenceManager.project();
    if (project) {
      this.tryAddProject(project);
    }
    this._updateUI();
  }

  _updateUI() {
    this._toolbar.removeToolbarItems();
    const project = Persistence.networkPersistenceManager.project();
    if (project) {
      const enableCheckbox =
          new UI.ToolbarSettingCheckbox(Common.settings.moduleSetting('persistenceNetworkOverridesEnabled'));
      this._toolbar.appendToolbarItem(enableCheckbox);

      this._toolbar.appendToolbarItem(new UI.ToolbarSeparator(true));
      const clearButton = new UI.ToolbarButton(Common.UIString('Clear configuration'), 'largeicon-clear');
      clearButton.addEventListener(UI.ToolbarButton.Events.Click, () => {
        project.remove();
      });
      this._toolbar.appendToolbarItem(clearButton);
      return;
    }
    const title = Common.UIString('Select folder for overrides');
    const setupButton = new UI.ToolbarButton(title, 'largeicon-add', title);
    setupButton.addEventListener(UI.ToolbarButton.Events.Click, this._setupNewWorkspace, this);
    this._toolbar.appendToolbarItem(setupButton);
  }

  async _setupNewWorkspace() {
    const fileSystem = await Persistence.isolatedFileSystemManager.addFileSystem('overrides');
    if (!fileSystem) {
      return;
    }
    Common.settings.moduleSetting('persistenceNetworkOverridesEnabled').set(true);
  }

  /**
   * @override
   * @param {!Workspace.Project} project
   * @return {boolean}
   */
  acceptProject(project) {
    return project === Persistence.networkPersistenceManager.project();
  }
};

/**
 * @unrestricted
 */
Sources.ContentScriptsNavigatorView = class extends Sources.NavigatorView {
  constructor() {
    super();
    const placeholder = new UI.EmptyWidget('');
    this.setPlaceholder(placeholder);
    placeholder.appendParagraph().appendChild(UI.html`
      <div>${ls`Content scripts served by extensions appear here`}</div><br />
      ${UI.XLink.create('https://developer.chrome.com/extensions/content_scripts', ls`Learn more`)}
    `);
  }

  /**
   * @override
   * @param {!Workspace.Project} project
   * @return {boolean}
   */
  acceptProject(project) {
    return project.type() === Workspace.projectTypes.ContentScripts;
  }
};

/**
 * @unrestricted
 */
Sources.SnippetsNavigatorView = class extends Sources.NavigatorView {
  constructor() {
    super();
    const placeholder = new UI.EmptyWidget('');
    this.setPlaceholder(placeholder);
    placeholder.appendParagraph().appendChild(UI.html`
      <div>${ls`Create and save code snippets for later reuse`}</div><br />
      ${UI.XLink.create('https://developers.google.com/web/tools/chrome-devtools/javascript/snippets', ls`Learn more`)}
    `);

    const toolbar = new UI.Toolbar('navigator-toolbar');
    const newButton = new UI.ToolbarButton('', 'largeicon-add', Common.UIString('New snippet'));
    newButton.addEventListener(UI.ToolbarButton.Events.Click, () => this.create(Snippets.project, ''));
    toolbar.appendToolbarItem(newButton);
    this.contentElement.insertBefore(toolbar.element, this.contentElement.firstChild);
  }

  /**
   * @override
   * @param {!Workspace.Project} project
   * @return {boolean}
   */
  acceptProject(project) {
    return Snippets.isSnippetsProject(project);
  }

  /**
   * @override
   * @param {!Event} event
   */
  handleContextMenu(event) {
    const contextMenu = new UI.ContextMenu(event);
    contextMenu.headerSection().appendItem(ls`Create new snippet`, () => this.create(Snippets.project, ''));
    contextMenu.show();
  }

  /**
   * @override
   * @param {!Event} event
   * @param {!Sources.NavigatorUISourceCodeTreeNode} node
   */
  handleFileContextMenu(event, node) {
    const uiSourceCode = node.uiSourceCode();
    const contextMenu = new UI.ContextMenu(event);
    contextMenu.headerSection().appendItem(Common.UIString('Run'), () => Snippets.evaluateScriptSnippet(uiSourceCode));
    contextMenu.editSection().appendItem(Common.UIString('Rename\u2026'), () => this.rename(node, false));
    contextMenu.editSection().appendItem(
        Common.UIString('Remove'), () => uiSourceCode.project().deleteFile(uiSourceCode));
    contextMenu.saveSection().appendItem(Common.UIString('Save as...'), this._handleSaveAs.bind(this, uiSourceCode));
    contextMenu.show();
  }

  /**
   * @param {!Workspace.UISourceCode} uiSourceCode
   */
  async _handleSaveAs(uiSourceCode) {
    uiSourceCode.commitWorkingCopy();
    const {content} = await uiSourceCode.requestContent();
    Workspace.fileManager.save(uiSourceCode.url(), content || '', true);
    Workspace.fileManager.close(uiSourceCode.url());
  }
};

/**
 * @implements {UI.ActionDelegate}
 */
Sources.ActionDelegate = class {
  /**
   * @override
   * @param {!UI.Context} context
   * @param {string} actionId
   * @return {boolean}
   */
  handleAction(context, actionId) {
    switch (actionId) {
      case 'sources.create-snippet':
        Snippets.project.createFile('', null, '').then(uiSourceCode => Common.Revealer.reveal(uiSourceCode));
        return true;
      case 'sources.add-folder-to-workspace':
        Persistence.isolatedFileSystemManager.addFileSystem();
        return true;
    }
    return false;
  }
};
