/*
 * Copyright (C) 2007, 2008 Apple Inc.  All rights reserved.
 * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
 * Copyright (C) 2009 Joseph Pecoraro
 *
 * 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.
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE 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 APPLE 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.
 */

/**
 * @implements {UI.Searchable}
 * @implements {SDK.SDKModelObserver<!SDK.DOMModel>}
 * @implements {UI.ViewLocationResolver}
 * @unrestricted
 */
export default class ElementsPanel extends UI.Panel {
  constructor() {
    super('elements');
    this.registerRequiredCSS('elements/elementsPanel.css');

    this._splitWidget = new UI.SplitWidget(true, true, 'elementsPanelSplitViewState', 325, 325);
    this._splitWidget.addEventListener(
        UI.SplitWidget.Events.SidebarSizeChanged, this._updateTreeOutlineVisibleWidth.bind(this));
    this._splitWidget.show(this.element);

    this._searchableView = new UI.SearchableView(this);
    this._searchableView.setMinimumSize(25, 28);
    this._searchableView.setPlaceholder(Common.UIString('Find by string, selector, or XPath'));
    const stackElement = this._searchableView.element;

    this._contentElement = createElement('div');
    const crumbsContainer = createElement('div');
    stackElement.appendChild(this._contentElement);
    stackElement.appendChild(crumbsContainer);

    this._splitWidget.setMainWidget(this._searchableView);
    /** @type {?_splitMode} */
    this._splitMode = null;

    this._contentElement.id = 'elements-content';
    // FIXME: crbug.com/425984
    if (Common.moduleSetting('domWordWrap').get()) {
      this._contentElement.classList.add('elements-wrap');
    }
    Common.moduleSetting('domWordWrap').addChangeListener(this._domWordWrapSettingChanged.bind(this));

    crumbsContainer.id = 'elements-crumbs';
    this._breadcrumbs = new Elements.ElementsBreadcrumbs();
    this._breadcrumbs.show(crumbsContainer);
    this._breadcrumbs.addEventListener(Elements.ElementsBreadcrumbs.Events.NodeSelected, this._crumbNodeSelected, this);

    this._stylesWidget = new Elements.StylesSidebarPane();
    this._computedStyleWidget = new Elements.ComputedStyleWidget();
    this._metricsWidget = new Elements.MetricsSidebarPane();

    Common.moduleSetting('sidebarPosition').addChangeListener(this._updateSidebarPosition.bind(this));
    this._updateSidebarPosition();

    /** @type {!Array.<!Elements.ElementsTreeOutline>} */
    this._treeOutlines = [];
    /** @type {!Map<!Elements.ElementsTreeOutline, !Element>} */
    this._treeOutlineHeaders = new Map();
    SDK.targetManager.observeModels(SDK.DOMModel, this);
    SDK.targetManager.addEventListener(
        SDK.TargetManager.Events.NameChanged,
        event => this._targetNameChanged(/** @type {!SDK.Target} */ (event.data)));
    Common.moduleSetting('showUAShadowDOM').addChangeListener(this._showUAShadowDOMChanged.bind(this));
    SDK.targetManager.addModelListener(
        SDK.DOMModel, SDK.DOMModel.Events.DocumentUpdated, this._documentUpdatedEvent, this);
    Extensions.extensionServer.addEventListener(
        Extensions.ExtensionServer.Events.SidebarPaneAdded, this._extensionSidebarPaneAdded, this);

    /**
     * @type {!Array.<{domModel: !SDK.DOMModel, index: number, node: (?SDK.DOMNode|undefined)}>|undefined}
     */
    this._searchResults;
  }

  /**
   * @return {!ElementsPanel}
   */
  static instance() {
    return /** @type {!ElementsPanel} */ (self.runtime.sharedInstance(ElementsPanel));
  }

  /**
   * @param {!SDK.CSSProperty} cssProperty
   */
  _revealProperty(cssProperty) {
    return this.sidebarPaneView.showView(this._stylesViewToReveal).then(() => {
      this._stylesWidget.revealProperty(/** @type {!SDK.CSSProperty} */ (cssProperty));
    });
  }

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

  /**
   * @param {?UI.Widget} widget
   * @param {?UI.ToolbarToggle} toggle
   */
  showToolbarPane(widget, toggle) {
    // TODO(luoe): remove this function once its providers have an alternative way to reveal their views.
    this._stylesWidget.showToolbarPane(widget, toggle);
  }

  /**
   * @override
   * @param {!SDK.DOMModel} domModel
   */
  modelAdded(domModel) {
    const parentModel = domModel.parentModel();
    let treeOutline = parentModel ? Elements.ElementsTreeOutline.forDOMModel(parentModel) : null;
    if (!treeOutline) {
      treeOutline = new Elements.ElementsTreeOutline(true, true);
      treeOutline.setWordWrap(Common.moduleSetting('domWordWrap').get());
      treeOutline.addEventListener(
          Elements.ElementsTreeOutline.Events.SelectedNodeChanged, this._selectedNodeChanged, this);
      treeOutline.addEventListener(
          Elements.ElementsTreeOutline.Events.ElementsTreeUpdated, this._updateBreadcrumbIfNeeded, this);
      new Elements.ElementsTreeElementHighlighter(treeOutline);
      this._treeOutlines.push(treeOutline);
      if (domModel.target().parentTarget()) {
        this._treeOutlineHeaders.set(treeOutline, createElementWithClass('div', 'elements-tree-header'));
        this._targetNameChanged(domModel.target());
      }
    }
    treeOutline.wireToDOMModel(domModel);

    // Perform attach if necessary.
    if (this.isShowing()) {
      this.wasShown();
    }
  }

  /**
   * @override
   * @param {!SDK.DOMModel} domModel
   */
  modelRemoved(domModel) {
    const treeOutline = Elements.ElementsTreeOutline.forDOMModel(domModel);
    treeOutline.unwireFromDOMModel(domModel);
    if (domModel.parentModel()) {
      return;
    }
    this._treeOutlines.remove(treeOutline);
    const header = this._treeOutlineHeaders.get(treeOutline);
    if (header) {
      header.remove();
    }
    this._treeOutlineHeaders.delete(treeOutline);
    treeOutline.element.remove();
  }

  /**
   * @param {!SDK.Target} target
   */
  _targetNameChanged(target) {
    const domModel = target.model(SDK.DOMModel);
    if (!domModel) {
      return;
    }
    const treeOutline = Elements.ElementsTreeOutline.forDOMModel(domModel);
    if (!treeOutline) {
      return;
    }
    const header = this._treeOutlineHeaders.get(treeOutline);
    if (!header) {
      return;
    }
    header.removeChildren();
    header.createChild('div', 'elements-tree-header-frame').textContent = Common.UIString('Frame');
    header.appendChild(Components.Linkifier.linkifyURL(target.inspectedURL(), {text: target.name()}));
  }

  _updateTreeOutlineVisibleWidth() {
    if (!this._treeOutlines.length) {
      return;
    }

    let width = this._splitWidget.element.offsetWidth;
    if (this._splitWidget.isVertical()) {
      width -= this._splitWidget.sidebarSize();
    }
    for (let i = 0; i < this._treeOutlines.length; ++i) {
      this._treeOutlines[i].setVisibleWidth(width);
    }

    this._breadcrumbs.updateSizes();
  }

  /**
   * @override
   */
  focus() {
    if (this._treeOutlines.length) {
      this._treeOutlines[0].focus();
    }
  }

  /**
   * @override
   * @return {!UI.SearchableView}
   */
  searchableView() {
    return this._searchableView;
  }

  /**
   * @override
   */
  wasShown() {
    UI.context.setFlavor(ElementsPanel, this);

    for (let i = 0; i < this._treeOutlines.length; ++i) {
      const treeOutline = this._treeOutlines[i];
      // Attach heavy component lazily
      if (treeOutline.element.parentElement !== this._contentElement) {
        const header = this._treeOutlineHeaders.get(treeOutline);
        if (header) {
          this._contentElement.appendChild(header);
        }
        this._contentElement.appendChild(treeOutline.element);
      }
    }
    super.wasShown();
    this._breadcrumbs.update();

    const domModels = SDK.targetManager.models(SDK.DOMModel);
    for (const domModel of domModels) {
      if (domModel.parentModel()) {
        continue;
      }
      const treeOutline = Elements.ElementsTreeOutline.forDOMModel(domModel);
      treeOutline.setVisible(true);

      if (!treeOutline.rootDOMNode) {
        if (domModel.existingDocument()) {
          treeOutline.rootDOMNode = domModel.existingDocument();
          this._documentUpdated(domModel);
        } else {
          domModel.requestDocument();
        }
      }
    }
  }

  /**
   * @override
   */
  willHide() {
    SDK.OverlayModel.hideDOMNodeHighlight();
    for (let i = 0; i < this._treeOutlines.length; ++i) {
      const treeOutline = this._treeOutlines[i];
      treeOutline.setVisible(false);
      // Detach heavy component on hide
      this._contentElement.removeChild(treeOutline.element);
      const header = this._treeOutlineHeaders.get(treeOutline);
      if (header) {
        this._contentElement.removeChild(header);
      }
    }
    if (this._popoverHelper) {
      this._popoverHelper.hidePopover();
    }
    super.willHide();
    UI.context.setFlavor(ElementsPanel, null);
  }

  /**
   * @override
   */
  onResize() {
    this.element.window().requestAnimationFrame(this._updateSidebarPosition.bind(this));  // Do not force layout.
    this._updateTreeOutlineVisibleWidth();
  }

  /**
   * @param {!Common.Event} event
   */
  _selectedNodeChanged(event) {
    const selectedNode = /** @type {?SDK.DOMNode} */ (event.data.node);
    const focus = /** @type {boolean} */ (event.data.focus);
    for (const treeOutline of this._treeOutlines) {
      if (!selectedNode || Elements.ElementsTreeOutline.forDOMModel(selectedNode.domModel()) !== treeOutline) {
        treeOutline.selectDOMNode(null);
      }
    }

    this._breadcrumbs.setSelectedNode(selectedNode);

    UI.context.setFlavor(SDK.DOMNode, selectedNode);

    if (!selectedNode) {
      return;
    }
    selectedNode.setAsInspectedNode();
    if (focus) {
      this._selectedNodeOnReset = selectedNode;
      this._hasNonDefaultSelectedNode = true;
    }

    const executionContexts = selectedNode.domModel().runtimeModel().executionContexts();
    const nodeFrameId = selectedNode.frameId();
    for (const context of executionContexts) {
      if (context.frameId === nodeFrameId) {
        UI.context.setFlavor(SDK.ExecutionContext, context);
        break;
      }
    }
  }

  /**
   * @param {!Common.Event} event
   */
  _documentUpdatedEvent(event) {
    const domModel = /** @type {!SDK.DOMModel} */ (event.data);
    this._documentUpdated(domModel);
  }

  /**
   * @param {!SDK.DOMModel} domModel
   */
  _documentUpdated(domModel) {
    this._searchableView.resetSearch();

    if (!domModel.existingDocument()) {
      if (this.isShowing()) {
        domModel.requestDocument();
      }
      return;
    }

    this._hasNonDefaultSelectedNode = false;

    if (this._omitDefaultSelection) {
      return;
    }

    const savedSelectedNodeOnReset = this._selectedNodeOnReset;
    restoreNode.call(this, domModel, this._selectedNodeOnReset);

    /**
     * @param {!SDK.DOMModel} domModel
     * @param {?SDK.DOMNode} staleNode
     * @this {ElementsPanel}
     */
    async function restoreNode(domModel, staleNode) {
      const nodePath = staleNode ? staleNode.path() : null;

      const restoredNodeId = nodePath ? await domModel.pushNodeByPathToFrontend(nodePath) : null;

      if (savedSelectedNodeOnReset !== this._selectedNodeOnReset) {
        return;
      }
      let node = restoredNodeId ? domModel.nodeForId(restoredNodeId) : null;
      if (!node) {
        const inspectedDocument = domModel.existingDocument();
        node = inspectedDocument ? inspectedDocument.body || inspectedDocument.documentElement : null;
      }
      this._setDefaultSelectedNode(node);
      this._lastSelectedNodeSelectedForTest();
    }
  }

  _lastSelectedNodeSelectedForTest() {
  }

  /**
   * @param {?SDK.DOMNode} node
   */
  _setDefaultSelectedNode(node) {
    if (!node || this._hasNonDefaultSelectedNode || this._pendingNodeReveal) {
      return;
    }
    const treeOutline = Elements.ElementsTreeOutline.forDOMModel(node.domModel());
    if (!treeOutline) {
      return;
    }
    this.selectDOMNode(node);
    if (treeOutline.selectedTreeElement) {
      treeOutline.selectedTreeElement.expand();
    }
  }

  /**
   * @override
   */
  searchCanceled() {
    delete this._searchConfig;
    this._hideSearchHighlights();

    this._searchableView.updateSearchMatchesCount(0);

    delete this._currentSearchResultIndex;
    delete this._searchResults;

    SDK.DOMModel.cancelSearch();
  }

  /**
   * @override
   * @param {!UI.SearchableView.SearchConfig} searchConfig
   * @param {boolean} shouldJump
   * @param {boolean=} jumpBackwards
   */
  performSearch(searchConfig, shouldJump, jumpBackwards) {
    const query = searchConfig.query;

    const whitespaceTrimmedQuery = query.trim();
    if (!whitespaceTrimmedQuery.length) {
      return;
    }

    if (!this._searchConfig || this._searchConfig.query !== query) {
      this.searchCanceled();
    } else {
      this._hideSearchHighlights();
    }

    this._searchConfig = searchConfig;

    const showUAShadowDOM = Common.moduleSetting('showUAShadowDOM').get();
    const domModels = SDK.targetManager.models(SDK.DOMModel);
    const promises = domModels.map(domModel => domModel.performSearch(whitespaceTrimmedQuery, showUAShadowDOM));
    Promise.all(promises).then(resultCountCallback.bind(this));

    /**
     * @param {!Array.<number>} resultCounts
     * @this {ElementsPanel}
     */
    function resultCountCallback(resultCounts) {
      this._searchResults = [];
      for (let i = 0; i < resultCounts.length; ++i) {
        const resultCount = resultCounts[i];
        for (let j = 0; j < resultCount; ++j) {
          this._searchResults.push({domModel: domModels[i], index: j, node: undefined});
        }
      }
      this._searchableView.updateSearchMatchesCount(this._searchResults.length);
      if (!this._searchResults.length) {
        return;
      }
      if (this._currentSearchResultIndex >= this._searchResults.length) {
        this._currentSearchResultIndex = undefined;
      }

      let index = this._currentSearchResultIndex;

      if (shouldJump) {
        if (this._currentSearchResultIndex === undefined) {
          index = jumpBackwards ? -1 : 0;
        } else {
          index = jumpBackwards ? index - 1 : index + 1;
        }
        this._jumpToSearchResult(index);
      }
    }
  }

  _domWordWrapSettingChanged(event) {
    // FIXME: crbug.com/425984
    this._contentElement.classList.toggle('elements-wrap', event.data);
    for (let i = 0; i < this._treeOutlines.length; ++i) {
      this._treeOutlines[i].setWordWrap(/** @type {boolean} */ (event.data));
    }
  }

  switchToAndFocus(node) {
    // Reset search restore.
    this._searchableView.cancelSearch();
    UI.viewManager.showView('elements').then(() => this.selectDOMNode(node, true));
  }

  /**
   * @param {!Event} event
   * @return {?UI.PopoverRequest}
   */
  _getPopoverRequest(event) {
    let link = event.target;
    while (link && !link[Elements.ElementsTreeElement.HrefSymbol]) {
      link = link.parentElementOrShadowHost();
    }
    if (!link) {
      return null;
    }

    return {
      box: link.boxInWindow(),
      show: async popover => {
        const node = this.selectedDOMNode();
        if (!node) {
          return false;
        }
        const preview = await Components.ImagePreview.build(
            node.domModel().target(), link[Elements.ElementsTreeElement.HrefSymbol], true);
        if (preview) {
          popover.contentElement.appendChild(preview);
        }
        return !!preview;
      }
    };
  }

  _jumpToSearchResult(index) {
    if (!this._searchResults) {
      return;
    }

    this._currentSearchResultIndex = (index + this._searchResults.length) % this._searchResults.length;
    this._highlightCurrentSearchResult();
  }

  /**
   * @override
   */
  jumpToNextSearchResult() {
    if (!this._searchResults) {
      return;
    }
    this.performSearch(this._searchConfig, true);
  }

  /**
   * @override
   */
  jumpToPreviousSearchResult() {
    if (!this._searchResults) {
      return;
    }
    this.performSearch(this._searchConfig, true, true);
  }

  /**
   * @override
   * @return {boolean}
   */
  supportsCaseSensitiveSearch() {
    return false;
  }

  /**
   * @override
   * @return {boolean}
   */
  supportsRegexSearch() {
    return false;
  }

  _highlightCurrentSearchResult() {
    const index = this._currentSearchResultIndex;
    const searchResults = this._searchResults;
    if (!searchResults) {
      return;
    }
    const searchResult = searchResults[index];

    this._searchableView.updateCurrentMatchIndex(index);
    if (searchResult.node === null) {
      return;
    }

    if (typeof searchResult.node === 'undefined') {
      // No data for slot, request it.
      searchResult.domModel.searchResult(searchResult.index).then(node => {
        searchResult.node = node;
        this._highlightCurrentSearchResult();
      });
      return;
    }

    const treeElement = this._treeElementForNode(searchResult.node);
    searchResult.node.scrollIntoView();
    if (treeElement) {
      treeElement.highlightSearchResults(this._searchConfig.query);
      treeElement.reveal();
      const matches = treeElement.listItemElement.getElementsByClassName(UI.highlightedSearchResultClassName);
      if (matches.length) {
        matches[0].scrollIntoViewIfNeeded(false);
      }
    }
  }

  _hideSearchHighlights() {
    if (!this._searchResults || !this._searchResults.length || this._currentSearchResultIndex === undefined) {
      return;
    }
    const searchResult = this._searchResults[this._currentSearchResultIndex];
    if (!searchResult.node) {
      return;
    }
    const treeOutline = Elements.ElementsTreeOutline.forDOMModel(searchResult.node.domModel());
    const treeElement = treeOutline.findTreeElement(searchResult.node);
    if (treeElement) {
      treeElement.hideSearchHighlights();
    }
  }

  /**
   * @return {?SDK.DOMNode}
   */
  selectedDOMNode() {
    for (let i = 0; i < this._treeOutlines.length; ++i) {
      const treeOutline = this._treeOutlines[i];
      if (treeOutline.selectedDOMNode()) {
        return treeOutline.selectedDOMNode();
      }
    }
    return null;
  }

  /**
   * @param {!SDK.DOMNode} node
   * @param {boolean=} focus
   */
  selectDOMNode(node, focus) {
    for (const treeOutline of this._treeOutlines) {
      const outline = Elements.ElementsTreeOutline.forDOMModel(node.domModel());
      if (outline === treeOutline) {
        treeOutline.selectDOMNode(node, focus);
      } else {
        treeOutline.selectDOMNode(null);
      }
    }
  }

  /**
   * @param {!Common.Event} event
   */
  _updateBreadcrumbIfNeeded(event) {
    const nodes = /** @type {!Array.<!SDK.DOMNode>} */ (event.data);
    this._breadcrumbs.updateNodes(nodes);
  }

  /**
   * @param {!Common.Event} event
   */
  _crumbNodeSelected(event) {
    const node = /** @type {!SDK.DOMNode} */ (event.data);
    this.selectDOMNode(node, true);
  }

  /**
   * @param {?SDK.DOMNode} node
   * @return {?Elements.ElementsTreeOutline}
   */
  _treeOutlineForNode(node) {
    if (!node) {
      return null;
    }
    return Elements.ElementsTreeOutline.forDOMModel(node.domModel());
  }

  /**
   * @param {!SDK.DOMNode} node
   * @return {?Elements.ElementsTreeElement}
   */
  _treeElementForNode(node) {
    const treeOutline = this._treeOutlineForNode(node);
    return /** @type {?Elements.ElementsTreeElement} */ (treeOutline.findTreeElement(node));
  }

  /**
   * @param {!SDK.DOMNode} node
   * @return {!SDK.DOMNode}
   */
  _leaveUserAgentShadowDOM(node) {
    let userAgentShadowRoot;
    while ((userAgentShadowRoot = node.ancestorUserAgentShadowRoot()) && userAgentShadowRoot.parentNode) {
      node = userAgentShadowRoot.parentNode;
    }
    return node;
  }

  /**
   * @param {!SDK.DOMNode} node
   * @param {boolean} focus
   * @param {boolean=} omitHighlight
   * @return {!Promise}
   */
  revealAndSelectNode(node, focus, omitHighlight) {
    this._omitDefaultSelection = true;

    node = Common.moduleSetting('showUAShadowDOM').get() ? node : this._leaveUserAgentShadowDOM(node);
    if (!omitHighlight) {
      node.highlightForTwoSeconds();
    }

    return UI.viewManager.showView('elements', false, !focus).then(() => {
      this.selectDOMNode(node, focus);
      delete this._omitDefaultSelection;

      if (!this._notFirstInspectElement) {
        Elements.ElementsPanel._firstInspectElementNodeNameForTest = node.nodeName();
        Elements.ElementsPanel._firstInspectElementCompletedForTest();
        Host.InspectorFrontendHost.inspectElementCompleted();
      }
      this._notFirstInspectElement = true;
    });
  }

  _showUAShadowDOMChanged() {
    for (let i = 0; i < this._treeOutlines.length; ++i) {
      this._treeOutlines[i].update();
    }
  }

  /**
   * @param {!Element} stylePaneWrapperElement
   */
  _setupTextSelectionHack(stylePaneWrapperElement) {
    // We "extend" the sidebar area when dragging, in order to keep smooth text
    // selection. It should be replaced by 'user-select: contain' in the future.
    const uninstallHackBound = uninstallHack.bind(this);

    // Fallback to cover unforeseen cases where text selection has ended.
    const uninstallHackOnMousemove = event => {
      if (event.buttons === 0) {
        uninstallHack.call(this);
      }
    };

    stylePaneWrapperElement.addEventListener('mousedown', event => {
      if (event.which !== 1) {
        return;
      }
      this._splitWidget.element.classList.add('disable-resizer-for-elements-hack');
      stylePaneWrapperElement.style.setProperty('height', `${stylePaneWrapperElement.offsetHeight}px`);
      const largeLength = 1000000;
      stylePaneWrapperElement.style.setProperty('left', `${- 1 * largeLength}px`);
      stylePaneWrapperElement.style.setProperty('padding-left', `${largeLength}px`);
      stylePaneWrapperElement.style.setProperty('width', `calc(100% + ${largeLength}px)`);
      stylePaneWrapperElement.style.setProperty('position', `fixed`);

      stylePaneWrapperElement.window().addEventListener('blur', uninstallHackBound);
      stylePaneWrapperElement.window().addEventListener('contextmenu', uninstallHackBound, true);
      stylePaneWrapperElement.window().addEventListener('dragstart', uninstallHackBound, true);
      stylePaneWrapperElement.window().addEventListener('mousemove', uninstallHackOnMousemove, true);
      stylePaneWrapperElement.window().addEventListener('mouseup', uninstallHackBound, true);
      stylePaneWrapperElement.window().addEventListener('visibilitychange', uninstallHackBound);
    }, true);

    /**
     * @this {!ElementsPanel}
     */
    function uninstallHack() {
      this._splitWidget.element.classList.remove('disable-resizer-for-elements-hack');
      stylePaneWrapperElement.style.removeProperty('left');
      stylePaneWrapperElement.style.removeProperty('padding-left');
      stylePaneWrapperElement.style.removeProperty('width');
      stylePaneWrapperElement.style.removeProperty('position');

      stylePaneWrapperElement.window().removeEventListener('blur', uninstallHackBound);
      stylePaneWrapperElement.window().removeEventListener('contextmenu', uninstallHackBound, true);
      stylePaneWrapperElement.window().removeEventListener('dragstart', uninstallHackBound, true);
      stylePaneWrapperElement.window().removeEventListener('mousemove', uninstallHackOnMousemove, true);
      stylePaneWrapperElement.window().removeEventListener('mouseup', uninstallHackBound, true);
      stylePaneWrapperElement.window().removeEventListener('visibilitychange', uninstallHackBound);
    }
  }

  _updateSidebarPosition() {
    if (this.sidebarPaneView && this.sidebarPaneView.tabbedPane().shouldHideOnDetach()) {
      return;
    }  // We can't reparent extension iframes.

    let splitMode;
    const position = Common.moduleSetting('sidebarPosition').get();
    if (position === 'right' || (position === 'auto' && UI.inspectorView.element.offsetWidth > 680)) {
      splitMode = _splitMode.Vertical;
    } else if (UI.inspectorView.element.offsetWidth > 415) {
      splitMode = _splitMode.Horizontal;
    } else {
      splitMode = _splitMode.Slim;
    }

    if (this.sidebarPaneView && splitMode === this._splitMode) {
      return;
    }
    this._splitMode = splitMode;

    const extensionSidebarPanes = Extensions.extensionServer.sidebarPanes();
    let lastSelectedTabId = null;
    if (this.sidebarPaneView) {
      lastSelectedTabId = this.sidebarPaneView.tabbedPane().selectedTabId;
      this.sidebarPaneView.tabbedPane().detach();
      this._splitWidget.uninstallResizer(this.sidebarPaneView.tabbedPane().headerElement());
    }

    this._splitWidget.setVertical(this._splitMode === _splitMode.Vertical);
    this.showToolbarPane(null /* widget */, null /* toggle */);

    const matchedStylePanesWrapper = new UI.VBox();
    matchedStylePanesWrapper.element.classList.add('style-panes-wrapper');
    this._stylesWidget.show(matchedStylePanesWrapper.element);
    this._setupTextSelectionHack(matchedStylePanesWrapper.element);

    const computedStylePanesWrapper = new UI.VBox();
    computedStylePanesWrapper.element.classList.add('style-panes-wrapper');
    this._computedStyleWidget.show(computedStylePanesWrapper.element);

    /**
     * @param {boolean} inComputedStyle
     * @this {ElementsPanel}
     */
    function showMetrics(inComputedStyle) {
      if (inComputedStyle) {
        this._metricsWidget.show(computedStylePanesWrapper.element, this._computedStyleWidget.element);
      } else {
        this._metricsWidget.show(matchedStylePanesWrapper.element);
      }
    }

    /**
     * @param {!Common.Event} event
     * @this {ElementsPanel}
     */
    function tabSelected(event) {
      const tabId = /** @type {string} */ (event.data.tabId);
      if (tabId === Common.UIString('Computed')) {
        showMetrics.call(this, true);
      } else if (tabId === Common.UIString('Styles')) {
        showMetrics.call(this, false);
      }
    }

    this.sidebarPaneView = UI.viewManager.createTabbedLocation(() => UI.viewManager.showView('elements'));
    const tabbedPane = this.sidebarPaneView.tabbedPane();
    if (this._popoverHelper) {
      this._popoverHelper.hidePopover();
    }
    this._popoverHelper = new UI.PopoverHelper(tabbedPane.element, this._getPopoverRequest.bind(this));
    this._popoverHelper.setHasPadding(true);
    this._popoverHelper.setTimeout(0);

    if (this._splitMode !== _splitMode.Vertical) {
      this._splitWidget.installResizer(tabbedPane.headerElement());
    }

    const stylesView = new UI.SimpleView(Common.UIString('Styles'));
    this.sidebarPaneView.appendView(stylesView);
    if (splitMode === _splitMode.Horizontal) {
      // Styles and computed are merged into a single tab.
      stylesView.element.classList.add('flex-auto');

      const splitWidget = new UI.SplitWidget(true, true, 'stylesPaneSplitViewState', 215);
      splitWidget.show(stylesView.element);
      splitWidget.setMainWidget(matchedStylePanesWrapper);
      splitWidget.setSidebarWidget(computedStylePanesWrapper);
    } else {
      // Styles and computed are in separate tabs.
      stylesView.element.classList.add('flex-auto');
      matchedStylePanesWrapper.show(stylesView.element);

      const computedView = new UI.SimpleView(Common.UIString('Computed'));
      computedView.element.classList.add('composite', 'fill');
      computedStylePanesWrapper.show(computedView.element);

      tabbedPane.addEventListener(UI.TabbedPane.Events.TabSelected, tabSelected, this);
      this.sidebarPaneView.appendView(computedView);
    }
    this._stylesViewToReveal = stylesView;

    showMetrics.call(this, this._splitMode === _splitMode.Horizontal);

    this.sidebarPaneView.appendApplicableItems('elements-sidebar');
    for (let i = 0; i < extensionSidebarPanes.length; ++i) {
      this._addExtensionSidebarPane(extensionSidebarPanes[i]);
    }

    if (lastSelectedTabId) {
      this.sidebarPaneView.tabbedPane().selectTab(lastSelectedTabId);
    }

    this._splitWidget.setSidebarWidget(this.sidebarPaneView.tabbedPane());
  }

  /**
   * @param {!Common.Event} event
   */
  _extensionSidebarPaneAdded(event) {
    const pane = /** @type {!Extensions.ExtensionSidebarPane} */ (event.data);
    this._addExtensionSidebarPane(pane);
  }

  /**
   * @param {!Extensions.ExtensionSidebarPane} pane
   */
  _addExtensionSidebarPane(pane) {
    if (pane.panelName() === this.name) {
      this.sidebarPaneView.appendView(pane);
    }
  }
}

/** @enum {symbol} */
export const _splitMode = {
  Vertical: Symbol('Vertical'),
  Horizontal: Symbol('Horizontal'),
  Slim: Symbol('Slim'),
};

/**
 * @implements {UI.ContextMenu.Provider}
 * @unrestricted
 */
export class ContextMenuProvider {
  /**
   * @override
   * @param {!Event} event
   * @param {!UI.ContextMenu} contextMenu
   * @param {!Object} object
   */
  appendApplicableItems(event, contextMenu, object) {
    if (!(object instanceof SDK.RemoteObject && (/** @type {!SDK.RemoteObject} */ (object)).isNode()) &&
        !(object instanceof SDK.DOMNode) && !(object instanceof SDK.DeferredDOMNode)) {
      return;
    }

    // Skip adding "Reveal..." menu item for our own tree outline.
    if (ElementsPanel.instance().element.isAncestor(/** @type {!Node} */ (event.target))) {
      return;
    }
    const commandCallback = Common.Revealer.reveal.bind(Common.Revealer, object);
    contextMenu.revealSection().appendItem(Common.UIString('Reveal in Elements panel'), commandCallback);
  }
}

/**
 * @implements {Common.Revealer}
 * @unrestricted
 */
export class DOMNodeRevealer {
  /**
   * @override
   * @param {!Object} node
   * @param {boolean=} omitFocus
   * @return {!Promise}
   */
  reveal(node, omitFocus) {
    const panel = ElementsPanel.instance();
    panel._pendingNodeReveal = true;

    return new Promise(revealPromise);

    /**
     * @param {function(undefined)} resolve
     * @param {function(!Error)} reject
     */
    function revealPromise(resolve, reject) {
      if (node instanceof SDK.DOMNode) {
        onNodeResolved(/** @type {!SDK.DOMNode} */ (node));
      } else if (node instanceof SDK.DeferredDOMNode) {
        (/** @type {!SDK.DeferredDOMNode} */ (node)).resolve(onNodeResolved);
      } else if (node instanceof SDK.RemoteObject) {
        const domModel = /** @type {!SDK.RemoteObject} */ (node).runtimeModel().target().model(SDK.DOMModel);
        if (domModel) {
          domModel.pushObjectAsNodeToFrontend(node).then(onNodeResolved);
        } else {
          reject(new Error('Could not resolve a node to reveal.'));
        }
      } else {
        reject(new Error('Can\'t reveal a non-node.'));
        panel._pendingNodeReveal = false;
      }

      /**
       * @param {?SDK.DOMNode} resolvedNode
       */
      function onNodeResolved(resolvedNode) {
        panel._pendingNodeReveal = false;

        // A detached node could still have a parent and ownerDocument
        // properties, which means stepping up through the hierarchy to ensure
        // that the root node is the document itself. Any break implies
        // detachment.
        let currentNode = resolvedNode;
        while (currentNode.parentNode) {
          currentNode = currentNode.parentNode;
        }
        const isDetached = !(currentNode instanceof SDK.DOMDocument);

        const isDocument = node instanceof SDK.DOMDocument;
        if (!isDocument && isDetached) {
          const msg = ls`Node cannot be found in the current page.`;
          Common.console.warn(msg);
          reject(new Error(msg));
          return;
        }

        if (resolvedNode) {
          panel.revealAndSelectNode(resolvedNode, !omitFocus).then(resolve);
          return;
        }
        reject(new Error('Could not resolve node to reveal.'));
      }
    }
  }
}

/**
 * @implements {Common.Revealer}
 * @unrestricted
 */
export class CSSPropertyRevealer {
  /**
   * @override
   * @param {!Object} property
   * @return {!Promise}
   */
  reveal(property) {
    const panel = ElementsPanel.instance();
    return panel._revealProperty(/** @type {!SDK.CSSProperty} */ (property));
  }
}


/**
 * @implements {UI.ActionDelegate}
 * @unrestricted
 */
export class ElementsActionDelegate {
  /**
   * @override
   * @param {!UI.Context} context
   * @param {string} actionId
   * @return {boolean}
   */
  handleAction(context, actionId) {
    const node = UI.context.flavor(SDK.DOMNode);
    if (!node) {
      return true;
    }
    const treeOutline = Elements.ElementsTreeOutline.forDOMModel(node.domModel());
    if (!treeOutline) {
      return true;
    }

    switch (actionId) {
      case 'elements.hide-element':
        treeOutline.toggleHideElement(node);
        return true;
      case 'elements.edit-as-html':
        treeOutline.toggleEditAsHTML(node);
        return true;
      case 'elements.undo':
        SDK.domModelUndoStack.undo();
        ElementsPanel.instance()._stylesWidget.forceUpdate();
        return true;
      case 'elements.redo':
        SDK.domModelUndoStack.redo();
        ElementsPanel.instance()._stylesWidget.forceUpdate();
        return true;
    }
    return false;
  }
}

/**
 * @implements {Elements.MarkerDecorator}
 * @unrestricted
 */
export class PseudoStateMarkerDecorator {
  /**
   * @override
   * @param {!SDK.DOMNode} node
   * @return {?{title: string, color: string}}
   */
  decorate(node) {
    return {
      color: 'orange',
      title: Common.UIString('Element state: %s', ':' + node.domModel().cssModel().pseudoState(node).join(', :'))
    };
  }
}

/* Legacy exported object */
self.Elements = self.Elements || {};

/* Legacy exported object */
Elements = Elements || {};

/** @constructor */
Elements.ElementsPanel = ElementsPanel;

// Sniffed in tests.
Elements.ElementsPanel._firstInspectElementCompletedForTest = function() {};

/** @enum {symbol} */
Elements.ElementsPanel._splitMode = _splitMode;

/** @constructor */
Elements.ElementsPanel.ContextMenuProvider = ContextMenuProvider;

/** @constructor */
Elements.ElementsPanel.DOMNodeRevealer = DOMNodeRevealer;

/** @constructor */
Elements.ElementsPanel.CSSPropertyRevealer = CSSPropertyRevealer;

/** @constructor */
Elements.ElementsActionDelegate = ElementsActionDelegate;

/** @constructor */
Elements.ElementsPanel.PseudoStateMarkerDecorator = PseudoStateMarkerDecorator;
