// 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.
import {ElementsPanel} from './ElementsPanel.js';

/**
 * @unrestricted
 */
export class ClassesPaneWidget extends UI.Widget {
  constructor() {
    super(true);
    this.registerRequiredCSS('elements/classesPaneWidget.css');
    this.contentElement.className = 'styles-element-classes-pane';
    const container = this.contentElement.createChild('div', 'title-container');
    this._input = container.createChild('div', 'new-class-input monospace');
    this.setDefaultFocusedElement(this._input);
    this._classesContainer = this.contentElement.createChild('div', 'source-code');
    this._classesContainer.classList.add('styles-element-classes-container');
    this._prompt = new ClassNamePrompt(this._nodeClasses.bind(this));
    this._prompt.setAutocompletionTimeout(0);
    this._prompt.renderAsBlock();

    const proxyElement = this._prompt.attach(this._input);
    this._prompt.setPlaceholder(Common.UIString('Add new class'));
    this._prompt.addEventListener(UI.TextPrompt.Events.TextChanged, this._onTextChanged, this);
    proxyElement.addEventListener('keydown', this._onKeyDown.bind(this), false);

    SDK.targetManager.addModelListener(SDK.DOMModel, SDK.DOMModel.Events.DOMMutated, this._onDOMMutated, this);
    /** @type {!Set<!SDK.DOMNode>} */
    this._mutatingNodes = new Set();
    /** @type {!Map<!SDK.DOMNode, string>} */
    this._pendingNodeClasses = new Map();
    this._updateNodeThrottler = new Common.Throttler(0);
    /** @type {?SDK.DOMNode} */
    this._previousTarget = null;
    UI.context.addFlavorChangeListener(SDK.DOMNode, this._onSelectedNodeChanged, this);
  }

  /**
   * @param {string} text
   * @return {!Array.<string>}
   */
  _splitTextIntoClasses(text) {
    return text.split(/[.,\s]/)
      .map(className => className.trim())
      .filter(className => className.length);
  }

  /**
   * @param {!Event} event
   */
  _onKeyDown(event) {
    if (!isEnterKey(event) && !isEscKey(event)) {
      return;
    }

    if (isEnterKey(event)) {
      event.consume();
      if (this._prompt.acceptAutoComplete()) {
        return;
      }
    }

    let text = event.target.textContent;
    if (isEscKey(event)) {
      if (!text.isWhitespace()) {
        event.consume(true);
      }
      text = '';
    }

    this._prompt.clearAutocomplete();
    event.target.textContent = '';

    const node = UI.context.flavor(SDK.DOMNode);
    if (!node) {
      return;
    }

    const classNames = this._splitTextIntoClasses(text);
    for (const className of classNames) {
      this._toggleClass(node, className, true);
    }
    this._installNodeClasses(node);
    this._update();
  }

  _onTextChanged() {
    const node = UI.context.flavor(SDK.DOMNode);
    if (!node) {
      return;
    }
    this._installNodeClasses(node);
  }

  /**
   * @param {!Common.Event} event
   */
  _onDOMMutated(event) {
    const node = /** @type {!SDK.DOMNode} */ (event.data);
    if (this._mutatingNodes.has(node)) {
      return;
    }
    delete node[ClassesPaneWidget._classesSymbol];
    this._update();
  }

  /**
   * @param {!Common.Event} event
   */
  _onSelectedNodeChanged(event) {
    if (this._previousTarget && this._prompt.text()) {
      this._input.textContent = '';
      this._installNodeClasses(this._previousTarget);
    }
    this._previousTarget = /** @type {?SDK.DOMNode} */ (event.data);
    this._update();
  }

  /**
   * @override
   */
  wasShown() {
    this._update();
  }

  _update() {
    if (!this.isShowing()) {
      return;
    }

    let node = UI.context.flavor(SDK.DOMNode);
    if (node) {
      node = node.enclosingElementOrSelf();
    }

    this._classesContainer.removeChildren();
    this._input.disabled = !node;

    if (!node) {
      return;
    }

    const classes = this._nodeClasses(node);
    const keys = classes.keysArray();
    keys.sort(String.caseInsensetiveComparator);
    for (let i = 0; i < keys.length; ++i) {
      const className = keys[i];
      const label = UI.CheckboxLabel.create(className, classes.get(className));
      label.classList.add('monospace');
      label.checkboxElement.addEventListener('click', this._onClick.bind(this, className), false);
      this._classesContainer.appendChild(label);
    }
  }

  /**
   * @param {string} className
   * @param {!Event} event
   */
  _onClick(className, event) {
    const node = UI.context.flavor(SDK.DOMNode);
    if (!node) {
      return;
    }
    const enabled = event.target.checked;
    this._toggleClass(node, className, enabled);
    this._installNodeClasses(node);
  }

  /**
   * @param {!SDK.DOMNode} node
   * @return {!Map<string, boolean>}
   */
  _nodeClasses(node) {
    let result = node[ClassesPaneWidget._classesSymbol];
    if (!result) {
      const classAttribute = node.getAttribute('class') || '';
      const classes = classAttribute.split(/\s/);
      result = new Map();
      for (let i = 0; i < classes.length; ++i) {
        const className = classes[i].trim();
        if (!className.length) {
          continue;
        }
        result.set(className, true);
      }
      node[ClassesPaneWidget._classesSymbol] = result;
    }
    return result;
  }

  /**
   * @param {!SDK.DOMNode} node
   * @param {string} className
   * @param {boolean} enabled
   */
  _toggleClass(node, className, enabled) {
    const classes = this._nodeClasses(node);
    classes.set(className, enabled);
  }

  /**
   * @param {!SDK.DOMNode} node
   */
  _installNodeClasses(node) {
    const classes = this._nodeClasses(node);
    const activeClasses = new Set();
    for (const className of classes.keys()) {
      if (classes.get(className)) {
        activeClasses.add(className);
      }
    }

    const additionalClasses = this._splitTextIntoClasses(this._prompt.textWithCurrentSuggestion());
    for (const className of additionalClasses) {
      activeClasses.add(className);
    }

    const newClasses = activeClasses.valuesArray();
    newClasses.sort();

    this._pendingNodeClasses.set(node, newClasses.join(' '));
    this._updateNodeThrottler.schedule(this._flushPendingClasses.bind(this));
  }

  /**
   * @return {!Promise}
   */
  _flushPendingClasses() {
    const promises = [];
    for (const node of this._pendingNodeClasses.keys()) {
      this._mutatingNodes.add(node);
      const promise = node.setAttributeValuePromise('class', this._pendingNodeClasses.get(node))
                          .then(onClassValueUpdated.bind(this, node));
      promises.push(promise);
    }
    this._pendingNodeClasses.clear();
    return Promise.all(promises);

    /**
     * @param {!SDK.DOMNode} node
     * @this {ClassesPaneWidget}
     */
    function onClassValueUpdated(node) {
      this._mutatingNodes.delete(node);
    }
  }
}

ClassesPaneWidget._classesSymbol = Symbol('ClassesPaneWidget._classesSymbol');

/**
 * @implements {UI.ToolbarItem.Provider}
 * @unrestricted
 */
export class ButtonProvider {
  constructor() {
    this._button = new UI.ToolbarToggle(Common.UIString('Element Classes'), '');
    this._button.setText('.cls');
    this._button.element.classList.add('monospace');
    this._button.addEventListener(UI.ToolbarButton.Events.Click, this._clicked, this);
    this._view = new ClassesPaneWidget();
  }

  _clicked() {
    ElementsPanel.instance().showToolbarPane(!this._view.isShowing() ? this._view : null, this._button);
  }

  /**
   * @override
   * @return {!UI.ToolbarItem}
   */
  item() {
    return this._button;
  }
}

/**
 * @unrestricted
 */
export class ClassNamePrompt extends UI.TextPrompt {
  /**
   * @param {function(!SDK.DOMNode):!Map<string, boolean>} nodeClasses
   */
  constructor(nodeClasses) {
    super();
    this._nodeClasses = nodeClasses;
    this.initialize(this._buildClassNameCompletions.bind(this), ' ');
    this.disableDefaultSuggestionForEmptyInput();
    this._selectedFrameId = '';
    this._classNamesPromise = null;
  }

  /**
   * @param {!SDK.DOMNode} selectedNode
   * @return {!Promise.<!Array.<string>>}
   */
  _getClassNames(selectedNode) {
    const promises = [];
    const completions = new Set();
    this._selectedFrameId = selectedNode.frameId();

    const cssModel = selectedNode.domModel().cssModel();
    const allStyleSheets = cssModel.allStyleSheets();
    for (const stylesheet of allStyleSheets) {
      if (stylesheet.frameId !== this._selectedFrameId) {
        continue;
      }
      const cssPromise = cssModel.classNamesPromise(stylesheet.id).then(classes => completions.addAll(classes));
      promises.push(cssPromise);
    }

    const domPromise = selectedNode.domModel()
                           .classNamesPromise(selectedNode.ownerDocument.id)
                           .then(classes => completions.addAll(classes));
    promises.push(domPromise);
    return Promise.all(promises).then(() => completions.valuesArray());
  }

  /**
   * @param {string} expression
   * @param {string} prefix
   * @param {boolean=} force
   * @return {!Promise<!UI.SuggestBox.Suggestions>}
   */
  _buildClassNameCompletions(expression, prefix, force) {
    if (!prefix || force) {
      this._classNamesPromise = null;
    }

    const selectedNode = UI.context.flavor(SDK.DOMNode);
    if (!selectedNode || (!prefix && !force && !expression.trim())) {
      return Promise.resolve([]);
    }

    if (!this._classNamesPromise || this._selectedFrameId !== selectedNode.frameId()) {
      this._classNamesPromise = this._getClassNames(selectedNode);
    }

    return this._classNamesPromise.then(completions => {
      const classesMap = this._nodeClasses(/** @type {!SDK.DOMNode} */ (selectedNode));
      completions = completions.filter(value => !classesMap.get(value));

      if (prefix[0] === '.') {
        completions = completions.map(value => '.' + value);
      }
      return completions.filter(value => value.startsWith(prefix)).sort().map(completion => ({text: completion}));
    });
  }
}
