// Copyright 2018 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.

cr.define('omnibox_output', function() {
  /**
   * Details how to display an autocomplete result data field.
   * @typedef {{
   *   header: string,
   *   url: string,
   *   propertyName: string,
   *   displayAlways: boolean,
   *   tooltip: string,
   * }}
   */
  let PresentationInfoRecord;

  /**
   * A constant that's used to decide what autocomplete result
   * properties to output in what order.
   * @type {!Array<!PresentationInfoRecord>}
   */
  const PROPERTY_OUTPUT_ORDER = [
    {
      header: 'Provider',
      url: '',
      propertyName: 'providerName',
      displayAlways: true,
      tooltip: 'The AutocompleteProvider suggesting this result.'
    },
    {
      header: 'Type',
      url: '',
      propertyName: 'type',
      displayAlways: true,
      tooltip: 'The type of the result.'
    },
    {
      header: 'Relevance',
      url: '',
      propertyName: 'relevance',
      displayAlways: true,
      tooltip: 'The result score. Higher is more relevant.'
    },
    {
      header: 'Contents',
      url: '',
      propertyName: 'contents',
      displayAlways: true,
      tooltip: 'The text that is presented identifying the result.'
    },
    {
      header: 'Description',
      url: '',
      propertyName: 'description',
      displayAlways: false,
      tooltip: 'The page title of the result.'
    },
    {
      header: 'CanBeDefault',
      url: '',
      propertyName: 'allowedToBeDefaultMatch',
      displayAlways: false,
      tooltip:
          'A green checkmark indicates that the result can be the default ' +
          'match(i.e., can be the match that pressing enter in the omnibox' +
          'navigates to).'
    },
    {
      header: 'Starred',
      url: '',
      propertyName: 'starred',
      displayAlways: false,
      tooltip:
          'A green checkmark indicates that the result has been bookmarked.'
    },
    {
      header: 'Hastabmatch',
      url: '',
      propertyName: 'hasTabMatch',
      displayAlways: false,
      tooltip:
          'A green checkmark indicates that the result URL matches an open' +
          'tab.'
    },
    {
      header: 'URL',
      url: '',
      propertyName: 'destinationUrl',
      displayAlways: true,
      tooltip: 'The URL for the result.'
    },
    {
      header: 'FillIntoEdit',
      url: '',
      propertyName: 'fillIntoEdit',
      displayAlways: false,
      tooltip: 'The text shown in the omnibox when the result is selected.'
    },
    {
      header: 'InlineAutocompletion',
      url: '',
      propertyName: 'inlineAutocompletion',
      displayAlways: false,
      tooltip: 'The text shown in the omnibox as a blue highlight selection ' +
          'following the cursor, if this match is shown inline.'
    },
    {
      header: 'Del',
      url: '',
      propertyName: 'deletable',
      displayAlways: false,
      tooltip:
          'A green checkmark indicates that the result can be deleted from ' +
          'the visit history.'
    },
    {
      header: 'Prev',
      url: '',
      propertyName: 'fromPrevious',
      displayAlways: false,
      tooltip: ''
    },
    {
      header: 'Tran',
      url:
          'https://cs.chromium.org/chromium/src/ui/base/page_transition_types.h?q=page_transition_types.h&sq=package:chromium&dr=CSs&l=14',
      propertyName: 'transition',
      displayAlways: false,
      tooltip: 'How the user got to the result.'
    },
    {
      header: 'Done',
      url: '',
      propertyName: 'providerDone',
      displayAlways: false,
      tooltip:
          'A green checkmark indicates that the provider is done looking ' +
          'for more results.'
    },
    {
      header: 'AssociatedKeyword',
      url: '',
      propertyName: 'associatedKeyword',
      displayAlways: false,
      tooltip: 'If non-empty, a "press tab to search" hint will be shown and ' +
          'will engage this keyword.'
    },
    {
      header: 'Keyword',
      url: '',
      propertyName: 'keyword',
      displayAlways: false,
      tooltip: 'The keyword of the search engine to be used.'
    },
    {
      header: 'Duplicates',
      url: '',
      propertyName: 'duplicates',
      displayAlways: false,
      tooltip: 'The number of matches that have been marked as duplicates of ' +
          'this match..'
    },
    {
      header: 'AdditionalInfo',
      url: '',
      propertyName: 'additionalInfo',
      displayAlways: false,
      tooltip: 'Provider-specific information about the result.'
    }
  ];

  /**
   * In addition to representing the rendered HTML element, OmniboxOutput also
   * provides a single public interface to interact with the output:
   * 1. Render tables from responses  (RenderDelegate)
   * 2. Control visibility based on display options (TODO)
   * 3. Control visibility and coloring based on search text (FilterDelegate)
   * 4. Export and copy output (CopyDelegate)
   * 5. Preserve inputs and reset inputs to default (TODO)
   * 6. Export and import inputs (TODO)
   * With regards to interacting with RenderDelegate, OmniboxOutput tracks and
   * aggregates responses from the C++ autocomplete controller. Typically, the
   * C++ controller returns 3 sets of results per query, unless a new query is
   * submitted before all 3 responses. OmniboxController also triggers
   * appending to and clearing of OmniboxOutput when appropriate (e.g., upon
   * receiving a new response or a change in display inputs).
   */
  class OmniboxOutput extends OmniboxElement {
    /** @return {string} */
    static get is() {
      return 'omnibox-output';
    }

    constructor() {
      super('omnibox-output-template');

      /** @type {!RenderDelegate} */
      this.renderDelegate = new RenderDelegate(this.$$('contents'));
      /** @type {!CopyDelegate} */
      this.copyDelegate = new CopyDelegate(this);
      /** @type {!FilterDelegate} */
      this.filterDelegate = new FilterDelegate(this);

      /** @type {!Array<!mojom.OmniboxResult>} */
      this.responses = [];
      /** @private {!QueryInputs} */
      this.queryInputs_ = /** @type {!QueryInputs} */ ({});
      /** @private {!DisplayInputs} */
      this.displayInputs_ = /** @type {!DisplayInputs} */ ({});
    }

    /** @param {!QueryInputs} queryInputs */
    updateQueryInputs(queryInputs) {
      this.queryInputs_ = queryInputs;
      this.refresh_();
    }

    /** @param {!DisplayInputs} displayInputs */
    updateDisplayInputs(displayInputs) {
      this.displayInputs_ = displayInputs;
      this.refresh_();
    }

    clearAutocompleteResponses() {
      this.responses = [];
      this.refresh_();
    }

    /** @param {!mojom.OmniboxResult} response */
    addAutocompleteResponse(response) {
      this.responses.push(response);
      this.refresh_();
    }

    /** @private */
    refresh_() {
      this.renderDelegate.refresh(
          this.queryInputs_, this.responses, this.displayInputs_);
    }

    /** @return {!Array<!OutputMatch>} */
    get matches() {
      return this.renderDelegate.matches;
    }
  }

  // Responsible for rendering the output HTML.
  class RenderDelegate {
    /** @param {!Element} containerElement */
    constructor(containerElement) {
      /** @private {!Element} */
      this.containerElement_ = containerElement;
    }

    /**
     * @param {!QueryInputs} queryInputs
     * @param {!Array<!mojom.OmniboxResult>} responses
     * @param {!DisplayInputs} displayInputs
     */
    refresh(queryInputs, responses, displayInputs) {
      if (!responses.length)
        return;

      /** @private {!Array<OutputResultsGroup>} */
      this.resultsGroup_;

      if (displayInputs.showIncompleteResults) {
        this.resultsGroup_ = responses.map(
            response =>
                new OutputResultsGroup(response, queryInputs.cursorPosition));
      } else {
        const lastResponse = responses[responses.length - 1];
        this.resultsGroup_ =
            [new OutputResultsGroup(lastResponse, queryInputs.cursorPosition)];
      }

      this.clearOutput_();
      this.resultsGroup_.forEach(
          resultsGroup =>
              this.containerElement_.appendChild(resultsGroup.render(
                  displayInputs.showDetails,
                  displayInputs.showIncompleteResults,
                  displayInputs.showAllProviders)));
    }

    /** @private */
    clearOutput_() {
      const contents = this.containerElement_;
      // Clears all children.
      while (contents.firstChild)
        contents.removeChild(contents.firstChild);
    }

    /** @return {string} */
    get visibletableText() {
      return this.containerElement_.innerText;
    }

    /** @return {!Array<!OutputMatch>} */
    get matches() {
      return this.resultsGroup_.flatMap(resultsGroup => resultsGroup.matches);
    }
  }

  /**
   * Helps track and render a results group. C++ Autocomplete typically returns
   * 3 result groups per query. It may return less if the next query is
   * submitted before all 3 have been returned. Each result group contains
   * top level information (e.g., how long the result took to generate), as well
   * as a single list of combined results and multiple lists of individual
   * results. Each of these lists is tracked and rendered by OutputResultsTable
   * below.
   */
  class OutputResultsGroup {
    /**
     * @param {!mojom.OmniboxResult} resultsGroup
     * @param {number} cursorPosition
     */
    constructor(resultsGroup, cursorPosition) {
      /** @struct */
      this.details = {
        cursorPosition,
        time: resultsGroup.timeSinceOmniboxStartedMs,
        done: resultsGroup.done,
        host: resultsGroup.host,
        isTypedHost: resultsGroup.isTypedHost
      };
      /** @type {!OutputResultsTable} */
      this.combinedResults =
          new OutputResultsTable(resultsGroup.combinedResults);
      /** @type {!Array<!OutputResultsTable>} */
      this.individualResultsList =
          resultsGroup.resultsByProvider
              .map(resultsWrapper => resultsWrapper.results)
              .filter(results => results.length > 0)
              .map(results => new OutputResultsTable(results));
    }

    /**
     * Creates a HTML Node representing this data.
     * @param {boolean} showDetails
     * @param {boolean} showIncompleteResults
     * @param {boolean} showAllProviders
     * @return {!Element}
     */
    render(showDetails, showIncompleteResults, showAllProviders) {
      const detailsAndTable =
          OmniboxElement.getTemplate('details-and-table-template');
      if (showDetails || showIncompleteResults) {
        detailsAndTable.querySelector('.details')
            .appendChild(this.renderDetails_());
      }

      const showAdditionalPropertiesColumn =
          this.showAdditionalPropertiesColumn_(showDetails);

      detailsAndTable.querySelector('.table').appendChild(
          OutputResultsTable.renderHeader(
              showDetails, showAdditionalPropertiesColumn));
      detailsAndTable.querySelector('.table').appendChild(
          this.combinedResults.render(showDetails));
      if (showAllProviders) {
        this.individualResultsList.forEach(individualResults => {
          detailsAndTable.querySelector('.table').appendChild(
              individualResults.renderInnerHeader(
                  showDetails, showAdditionalPropertiesColumn));
          detailsAndTable.querySelector('.table').appendChild(
              individualResults.render(showDetails));
        });
      }
      return detailsAndTable;
    }

    /**
     * @private
     * @return {!Element}
     */
    renderDetails_() {
      const details = OmniboxElement.getTemplate('details-template');
      details.querySelector('.cursor-position').textContent =
          this.details.cursorPosition;
      details.querySelector('.time').textContent = this.details.time;
      details.querySelector('.done').textContent = this.details.done;
      details.querySelector('.host').textContent = this.details.host;
      details.querySelector('.is-typed-host').textContent =
          this.details.isTypedHost;
      return details;
    }

    /**
     * @private
     * @param {boolean} showDetails
     * @return {boolean}
     */
    showAdditionalPropertiesColumn_(showDetails) {
      return showDetails &&
          (this.combinedResults.hasAdditionalProperties ||
           this.individualResultsList.some(
               results => results.hasAdditionalProperties));
    }

    /** @return {!Array<!OutputMatch>} */
    get matches() {
      return [this.combinedResults]
          .concat(this.individualResultsList)
          .flatMap(results => results.matches);
    }
  }

  /**
   * Helps track and render a list of results. Each result is tracked and
   * rendered by OutputMatch below.
   */
  class OutputResultsTable {
    /** @param {!Array<!mojom.AutocompleteMatch>} results */
    constructor(results) {
      /** @type {!Array<!OutputMatch>} */
      this.matches = results.map(match => new OutputMatch(match));
    }

    /**
     * @param {boolean} showDetails
     * @param {boolean} showAdditionalPropertiesColumn
     * @return {Element}
     */
    static renderHeader(showDetails, showAdditionalPropertiesColumn) {
      const head = document.createElement('thead');
      const row = document.createElement('tr');
      const cells =
          OutputMatch.displayedProperties(showDetails)
              .map(
                  ({header, url, tooltip}) =>
                      OutputMatch.renderHeaderCell(header, url, tooltip));
      if (showAdditionalPropertiesColumn)
        cells.push(OutputMatch.renderHeaderCell('Additional Properties'));
      cells.forEach(cell => row.appendChild(cell));
      head.appendChild(row);
      return head;
    }

    /**
     * Creates a HTML Node representing this data.
     * @param {boolean} showDetails
     * @return {!Element}
     */
    render(showDetails) {
      const body = document.createElement('tbody');
      this.matches.forEach(
          match => body.appendChild(match.render(showDetails)));
      return body;
    }

    /**
     * @param {boolean} showDetails
     * @param {boolean} showAdditionalPropertiesColumn
     * @return {!Element}
     */
    renderInnerHeader(showDetails, showAdditionalPropertiesColumn) {
      const head = document.createElement('thead');
      const row = document.createElement('tr');
      const cell = document.createElement('th');
      // Reserve 1 more column if showing the additional properties column.
      cell.colSpan = OutputMatch.displayedProperties(showDetails).length +
          showAdditionalPropertiesColumn;
      cell.textContent = this.matches[0].properties.providerName.value;
      row.appendChild(cell);
      head.appendChild(row);
      return head;
    }

    /** @return {boolean} */
    get hasAdditionalProperties() {
      return this.matches.some(match => match.hasAdditionalProperties);
    }
  }

  /** Helps track and render a single match. */
  class OutputMatch {
    /** @param {!mojom.AutocompleteMatch} match */
    constructor(match) {
      /** @dict */
      this.properties = {};
      let unconsumedProperties = {};
      Object.entries(match).forEach(propertyNameValueTuple => {
        // TODO(manukh) replace with destructuring when the styleguide is
        // updated
        // https://chromium-review.googlesource.com/c/chromium/src/+/1271915
        const propertyName = propertyNameValueTuple[0];
        const propertyValue = propertyNameValueTuple[1];

        if (PROPERTY_OUTPUT_ORDER.some(
                property => property.propertyName === propertyName)) {
          this.properties[propertyName] =
              OutputProperty.constructProperty(propertyName, propertyValue);
        } else {
          unconsumedProperties[propertyName] = propertyValue;
        }
      });
      /** @type {!OutputProperty} */
      this.additionalProperties = OutputProperty.constructProperty(
          'additionalProperties', unconsumedProperties);

      /** @type {!Element} */
      this.associatedElement;
    }

    /**
     * Creates a HTML Node representing this data.
     * @param {boolean} showDetails
     * @return {!Element}
     */
    render(showDetails) {
      const row = document.createElement('tr');
      OutputMatch.displayedProperties(showDetails)
          .map(property => this.properties[property.propertyName].render())
          .forEach(cell => row.appendChild(cell));

      if (showDetails && this.hasAdditionalProperties)
        row.appendChild(this.additionalProperties.render());

      this.associatedElement = row;
      return this.associatedElement;
    }

    /**
     * @param {string} name
     * @param {string=} url
     * @param {string=} tooltip
     * @return {!Element}
     */
    static renderHeaderCell(name, url, tooltip) {
      const cell = document.createElement('th');
      if (url) {
        const link = document.createElement('a');
        link.textContent = name;
        link.href = url;
        cell.appendChild(link);
      } else {
        cell.textContent = name;
      }
      cell.className =
          'column-' + name.replace(/[A-Z]/g, c => '-' + c.toLowerCase());
      cell.title = tooltip || '';
      return cell;
    }

    /**
     * @return {!Array<!PresentationInfoRecord>} Array representing which
     * columns need to be displayed.
     */
    static displayedProperties(showDetails) {
      return showDetails ?
          PROPERTY_OUTPUT_ORDER :
          PROPERTY_OUTPUT_ORDER.filter(property => property.displayAlways);
    }

    /**
     * @return {boolean} Used to determine if the additional properties column
     * needs to be displayed for this match.
     */
    get hasAdditionalProperties() {
      return Object.keys(this.additionalProperties).length > 0;
    }
  }

  /** @abstract */
  class OutputProperty {
    /**
     * @param {string} name
     * @param {*} value
     */
    constructor(name, value) {
      /** @type {string} */
      this.name = name;
      /** @type {*} */
      this.value = value;
    }

    /**
     * @param {string} name
     * @param {*} value
     * @return {!OutputProperty}
     */
    static constructProperty(name, value) {
      if (typeof value === 'boolean')
        return new OutputBooleanProperty(name, value);
      if (typeof value === 'object')
        // We check if the first element has key and value properties.
        if (value && value[0] && value[0].key && value[0].value)
          return new OutputKeyValueTuplesProperty(name, value);
        else
          return new OutputJsonProperty(name, value);
      const LINK_REGEX = /^(http|https|ftp|chrome|file):\/\//;
      if (LINK_REGEX.test(value))
        return new OutputLinkProperty(name, value);
      return new OutputTextProperty(name, value);
    }

    /**
     * @abstract
     * @return {!Element}
     */
    render() {}

    /** @return {string} */
    get text() {
      return this.value + '';
    }
  }

  class OutputBooleanProperty extends OutputProperty {
    /**
     * @override
     * @return {!Element}
     */
    render() {
      const cell = document.createElement('td');
      const icon = document.createElement('div');
      icon.className = this.value ? 'check-mark' : 'x-mark';
      icon.textContent = this.value;
      cell.appendChild(icon);
      return cell;
    }
  }

  class OutputKeyValueTuplesProperty extends OutputProperty {
    /**
     * @override
     * @return {!Element}
     */
    render() {
      const cell = document.createElement('td');
      const pre = document.createElement('pre');
      pre.textContent = this.text;
      cell.appendChild(pre);
      return cell;
    }

    /**
     * @override
     * @return {string}
     */
    get text() {
      return this.value.reduce(
          (prev, {key, value}) => `${prev}${key}: ${value}\n`, '');
    }
  }

  class OutputJsonProperty extends OutputProperty {
    /**
     * @override
     * @return {!Element}
     */
    render() {
      const cell = document.createElement('td');
      const pre = document.createElement('pre');
      pre.textContent = this.text;
      cell.appendChild(pre);
      return cell;
    }

    /**
     * @override
     * @return {string}
     */
    get text() {
      return JSON.stringify(this.value, null, 2);
    }
  }

  class OutputLinkProperty extends OutputProperty {
    /**
     * @override
     * @return {!Element}
     */
    render() {
      const cell = document.createElement('td');
      const link = document.createElement('a');
      link.textContent = this.value;
      link.href = this.value;
      cell.appendChild(link);
      return cell;
    }
  }

  class OutputTextProperty extends OutputProperty {
    /**
     * @override
     * @return {!Element}
     */
    render() {
      const cell = document.createElement('td');
      cell.textContent = this.value;
      return cell;
    }
  }

  /** Responsible for setting clipboard contents. */
  class CopyDelegate {
    /** @param {!omnibox_output.OmniboxOutput} omniboxOutput */
    constructor(omniboxOutput) {
      /** @private {!omnibox_output.OmniboxOutput} */
      this.omniboxOutput_ = omniboxOutput;
    }

    copyTextOutput() {
      this.copy_(this.omniboxOutput_.renderDelegate.visibletableText);
    }

    copyJsonOutput() {
      this.copy_(JSON.stringify(this.omniboxOutput_.responses, null, 2));
    }

    /**
     * @private
     * @param {string} value
     */
    copy_(value) {
      navigator.clipboard.writeText(value).catch(
          error => console.error('unable to copy to clipboard:', error));
    }
  }

  /** Responsible for highlighting and hiding rows using filter text. */
  class FilterDelegate {
    /** @param {!omnibox_output.OmniboxOutput} omniboxOutput */
    constructor(omniboxOutput) {
      /** @private {!omnibox_output.OmniboxOutput} */
      this.omniboxOutput_ = omniboxOutput;
    }

    /**
     * @param {string} filterText
     * @param {boolean} filterHide
     */
    filter(filterText, filterHide) {
      this.omniboxOutput_.matches.filter(match => match.associatedElement)
          .forEach(match => {
            const row = match.associatedElement;
            row.classList.remove('filtered-hidden');
            row.classList.remove('filtered-highlighted');

            if (!filterText)
              return;

            const isMatch = FilterDelegate.filterMatch_(match, filterText);
            row.classList.toggle('filtered-hidden', filterHide && !isMatch);
            row.classList.toggle(
                'filtered-highlighted', !filterHide && isMatch);
          });
    }

    /**
     * Checks if a omnibox match fuzzy-matches a filter string. Each character
     * of filterText must be present in the match text, either adjacent to the
     * previous matched character, or at the start of a new word (see
     * textToWords_).
     * E.g. `abc` matches `abc`, `a big cat`, `a-bigCat`, `a very big cat`, and
     * `an amBer cat`; but does not match `abigcat` or `an amber cat`.
     * `green rainbow` is matched by `gre rain`, but not by `gre bow`.
     * One exception is the first character, which may be matched mid-word.
     * E.g. `een rain` can also match `green rainbow`.
     * @private
     * @param {!OutputMatch} match
     * @param {string} filterText
     * @return {boolean}
     */
    static filterMatch_(match, filterText) {
      const row = match.associatedElement;
      const cells = Array.from(row.querySelectorAll('td'));
      const regexFilter = Array.from(filterText).join('(.*\\.)?');
      return cells
          .map(cell => FilterDelegate.textToWords_(cell.textContent).join('.'))
          .some(text => text.match(regexFilter));
    }

    /**
     * Splits a string into words, delimited by either capital letters, groups
     * of digits, or non alpha characters.
     * E.g., `https://google.com/the-dog-ate-134pies` will be split to:
     * https, :, /, /, google, ., com, /, the, -, dog, -, ate, -, 134, pies
     * We don't use `Array.split`, because we want to group digits, e.g. 134.
     * @private
     * @param {string} text
     * @return {!Array<string>}
     */
    static textToWords_(text) {
      return text.match(/[a-z]+|[A-Z][a-z]*|\d+|./g) || [];
    }
  }

  window.customElements.define(OmniboxOutput.is, OmniboxOutput);

  return {OmniboxOutput: OmniboxOutput};
});
