// Copyright (c) 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
 * @implements {UI.ContextFlavorListener}
 * @implements {UI.ToolbarItem.ItemsProvider}
 * @unrestricted
 */
export class XHRBreakpointsSidebarPane extends UI.VBox {
  constructor() {
    super(true);
    this.registerRequiredCSS('browser_debugger/xhrBreakpointsSidebarPane.css');

    this._listElement = this.contentElement.createChild('div', 'breakpoint-list hidden');
    this._emptyElement = this.contentElement.createChild('div', 'gray-info-message');
    this._emptyElement.textContent = Common.UIString('No breakpoints');

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

    this._addButton = new UI.ToolbarButton(Common.UIString('Add breakpoint'), 'largeicon-add');
    this._addButton.addEventListener(UI.ToolbarButton.Events.Click, this._addButtonClicked.bind(this));

    this._emptyElement.addEventListener('contextmenu', this._emptyElementContextMenu.bind(this), true);
    this._restoreBreakpoints();
    this._update();
  }

  /**
   * @override
   * @return {!Array<!UI.ToolbarItem>}
   */
  toolbarItems() {
    return [this._addButton];
  }

  _emptyElementContextMenu(event) {
    const contextMenu = new UI.ContextMenu(event);
    contextMenu.defaultSection().appendItem(Common.UIString('Add breakpoint'), this._addButtonClicked.bind(this));
    contextMenu.show();
  }

  async _addButtonClicked() {
    await UI.viewManager.showView('sources.xhrBreakpoints');

    const inputElementContainer = createElementWithClass('p', 'breakpoint-condition');
    inputElementContainer.textContent = Common.UIString('Break when URL contains:');

    const inputElement = inputElementContainer.createChild('span', 'breakpoint-condition-input');
    this._addListElement(inputElementContainer, /** @type {?Element} */ (this._listElement.firstChild));

    /**
     * @param {boolean} accept
     * @param {!Element} e
     * @param {string} text
     * @this {BrowserDebugger.XHRBreakpointsSidebarPane}
     */
    function finishEditing(accept, e, text) {
      this._removeListElement(inputElementContainer);
      if (accept) {
        SDK.domDebuggerManager.addXHRBreakpoint(text, true);
        this._setBreakpoint(text, true);
      }
    }

    const config = new UI.InplaceEditor.Config(finishEditing.bind(this, true), finishEditing.bind(this, false));
    UI.InplaceEditor.startEditing(inputElement, config);
  }

  /**
   * @param {string} url
   * @param {boolean} enabled
   */
  _setBreakpoint(url, enabled) {
    if (this._breakpointElements.has(url)) {
      this._breakpointElements.get(url)._checkboxElement.checked = enabled;
      return;
    }

    const element = createElementWithClass('div', 'breakpoint-entry');
    element._url = url;
    element.addEventListener('contextmenu', this._contextMenu.bind(this, url), true);

    const title = url ? Common.UIString('URL contains "%s"', url) : Common.UIString('Any XHR or fetch');
    const label = UI.CheckboxLabel.create(title, enabled);
    element.appendChild(label);
    label.checkboxElement.addEventListener('click', this._checkboxClicked.bind(this, url), false);
    element._checkboxElement = label.checkboxElement;

    label.classList.add('cursor-auto');
    label.textElement.addEventListener('dblclick', this._labelClicked.bind(this, url), false);

    let currentElement = /** @type {?Element} */ (this._listElement.firstChild);
    while (currentElement) {
      if (currentElement._url && currentElement._url < element._url) {
        break;
      }
      currentElement = /** @type {?Element} */ (currentElement.nextSibling);
    }
    this._addListElement(element, currentElement);
    this._breakpointElements.set(url, element);
  }

  /**
   * @param {string} url
   */
  _removeBreakpoint(url) {
    const element = this._breakpointElements.get(url);
    if (!element) {
      return;
    }

    this._removeListElement(element);
    this._breakpointElements.delete(url);
  }

  /**
   * @param {!Element} element
   * @param {?Node} beforeNode
   */
  _addListElement(element, beforeNode) {
    this._listElement.insertBefore(element, beforeNode);
    this._emptyElement.classList.add('hidden');
    this._listElement.classList.remove('hidden');
  }

  /**
   * @param {!Element} element
   */
  _removeListElement(element) {
    this._listElement.removeChild(element);
    if (!this._listElement.firstChild) {
      this._emptyElement.classList.remove('hidden');
      this._listElement.classList.add('hidden');
    }
  }

  _contextMenu(url, event) {
    const contextMenu = new UI.ContextMenu(event);

    /**
     * @this {BrowserDebugger.XHRBreakpointsSidebarPane}
     */
    function removeBreakpoint() {
      SDK.domDebuggerManager.removeXHRBreakpoint(url);
      this._removeBreakpoint(url);
    }

    /**
     * @this {BrowserDebugger.XHRBreakpointsSidebarPane}
     */
    function removeAllBreakpoints() {
      for (const url of this._breakpointElements.keys()) {
        SDK.domDebuggerManager.removeXHRBreakpoint(url);
        this._removeBreakpoint(url);
      }
    }
    const removeAllTitle = Common.UIString('Remove all breakpoints');

    contextMenu.defaultSection().appendItem(Common.UIString('Add breakpoint'), this._addButtonClicked.bind(this));
    contextMenu.defaultSection().appendItem(Common.UIString('Remove breakpoint'), removeBreakpoint.bind(this));
    contextMenu.defaultSection().appendItem(removeAllTitle, removeAllBreakpoints.bind(this));
    contextMenu.show();
  }

  _checkboxClicked(url, event) {
    SDK.domDebuggerManager.toggleXHRBreakpoint(url, event.target.checked);
  }

  _labelClicked(url) {
    const element = this._breakpointElements.get(url) || null;
    const inputElement = createElementWithClass('span', 'breakpoint-condition');
    inputElement.textContent = url;
    this._listElement.insertBefore(inputElement, element);
    element.classList.add('hidden');

    /**
     * @param {boolean} accept
     * @param {!Element} e
     * @param {string} text
     * @this {BrowserDebugger.XHRBreakpointsSidebarPane}
     */
    function finishEditing(accept, e, text) {
      this._removeListElement(inputElement);
      if (accept) {
        SDK.domDebuggerManager.removeXHRBreakpoint(url);
        this._removeBreakpoint(url);
        const enabled = element ? element._checkboxElement.checked : true;
        SDK.domDebuggerManager.addXHRBreakpoint(text, enabled);
        this._setBreakpoint(text, enabled);
      } else {
        element.classList.remove('hidden');
      }
    }

    UI.InplaceEditor.startEditing(
        inputElement, new UI.InplaceEditor.Config(finishEditing.bind(this, true), finishEditing.bind(this, false)));
  }

  /**
   * @override
   * @param {?Object} object
   */
  flavorChanged(object) {
    this._update();
  }

  _update() {
    const details = UI.context.flavor(SDK.DebuggerPausedDetails);
    if (!details || details.reason !== SDK.DebuggerModel.BreakReason.XHR) {
      if (this._highlightedElement) {
        this._highlightedElement.classList.remove('breakpoint-hit');
        delete this._highlightedElement;
      }
      return;
    }
    const url = details.auxData['breakpointURL'];
    const element = this._breakpointElements.get(url);
    if (!element) {
      return;
    }
    UI.viewManager.showView('sources.xhrBreakpoints');
    element.classList.add('breakpoint-hit');
    this._highlightedElement = element;
  }

  _restoreBreakpoints() {
    const breakpoints = SDK.domDebuggerManager.xhrBreakpoints();
    for (const url of breakpoints.keys()) {
      this._setBreakpoint(url, breakpoints.get(url));
    }
  }
}

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

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

/**
 * @constructor
 */
BrowserDebugger.XHRBreakpointsSidebarPane = XHRBreakpointsSidebarPane;
