/*
 * Copyright (c) 2012 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.
 */

/**
 * @unrestricted
 */
Sources.FilteredUISourceCodeListProvider = class extends QuickOpen.FilteredListWidget.Provider {
  constructor() {
    super();

    this._queryLineNumberAndColumnNumber = '';
    this._defaultScores = null;
    this._scorer = new Sources.FilePathScoreFunction('');
  }

  /**
   * @param {!Common.Event} event
   */
  _projectRemoved(event) {
    const project = /** @type {!Workspace.Project} */ (event.data);
    this._populate(project);
    this.refresh();
  }

  /**
   * @param {!Workspace.Project=} skipProject
   */
  _populate(skipProject) {
    /** @type {!Array.<!Workspace.UISourceCode>} */
    this._uiSourceCodes = [];
    const projects = Workspace.workspace.projects().filter(this.filterProject.bind(this));
    for (let i = 0; i < projects.length; ++i) {
      if (skipProject && projects[i] === skipProject) {
        continue;
      }
      const uiSourceCodes = projects[i].uiSourceCodes().filter(this._filterUISourceCode.bind(this));
      this._uiSourceCodes = this._uiSourceCodes.concat(uiSourceCodes);
    }
  }

  /**
   * @param {!Workspace.UISourceCode} uiSourceCode
   * @return {boolean}
   */
  _filterUISourceCode(uiSourceCode) {
    const binding = Persistence.persistence.binding(uiSourceCode);
    return !binding || binding.fileSystem === uiSourceCode;
  }

  /**
   * @param {?Workspace.UISourceCode} uiSourceCode
   * @param {number=} lineNumber
   * @param {number=} columnNumber
   */
  uiSourceCodeSelected(uiSourceCode, lineNumber, columnNumber) {
    // Overridden by subclasses
  }

  /**
   * @param {!Workspace.Project} project
   * @return {boolean}
   */
  filterProject(project) {
    return true;
    // Overridden by subclasses
  }

  /**
   * @override
   * @return {number}
   */
  itemCount() {
    return this._uiSourceCodes.length;
  }

  /**
   * @override
   * @param {number} itemIndex
   * @return {string}
   */
  itemKeyAt(itemIndex) {
    return this._uiSourceCodes[itemIndex].url();
  }

  /**
   * @protected
   * @param {?Map.<!Workspace.UISourceCode, number>} defaultScores
   */
  setDefaultScores(defaultScores) {
    this._defaultScores = defaultScores;
  }

  /**
   * @override
   * @param {number} itemIndex
   * @param {string} query
   * @return {number}
   */
  itemScoreAt(itemIndex, query) {
    const uiSourceCode = this._uiSourceCodes[itemIndex];
    const score = this._defaultScores ? (this._defaultScores.get(uiSourceCode) || 0) : 0;
    if (!query || query.length < 2) {
      return score;
    }

    if (this._query !== query) {
      this._query = query;
      this._scorer = new Sources.FilePathScoreFunction(query);
    }

    let multiplier = 10;
    if (uiSourceCode.project().type() === Workspace.projectTypes.FileSystem &&
        !Persistence.persistence.binding(uiSourceCode)) {
      multiplier = 5;
    }

    const fullDisplayName = uiSourceCode.fullDisplayName();
    return score + multiplier * this._scorer.score(fullDisplayName, null);
  }

  /**
   * @override
   * @param {number} itemIndex
   * @param {string} query
   * @param {!Element} titleElement
   * @param {!Element} subtitleElement
   */
  renderItem(itemIndex, query, titleElement, subtitleElement) {
    query = this.rewriteQuery(query);
    const uiSourceCode = this._uiSourceCodes[itemIndex];
    const fullDisplayName = uiSourceCode.fullDisplayName();
    const indexes = [];
    new Sources.FilePathScoreFunction(query).score(fullDisplayName, indexes);
    const fileNameIndex = fullDisplayName.lastIndexOf('/');

    titleElement.classList.add('monospace');
    subtitleElement.classList.add('monospace');
    titleElement.textContent = uiSourceCode.displayName() + (this._queryLineNumberAndColumnNumber || '');
    this._renderSubtitleElement(subtitleElement, fullDisplayName);
    subtitleElement.title = fullDisplayName;
    const ranges = [];
    for (let i = 0; i < indexes.length; ++i) {
      ranges.push({offset: indexes[i], length: 1});
    }

    if (indexes[0] > fileNameIndex) {
      for (let i = 0; i < ranges.length; ++i) {
        ranges[i].offset -= fileNameIndex + 1;
      }
      UI.highlightRangesWithStyleClass(titleElement, ranges, 'highlight');
    } else {
      UI.highlightRangesWithStyleClass(subtitleElement, ranges, 'highlight');
    }
  }

  /**
   * @param {!Element} element
   * @param {string} text
   */
  _renderSubtitleElement(element, text) {
    element.removeChildren();
    let splitPosition = text.lastIndexOf('/');
    if (text.length > 55) {
      splitPosition = text.length - 55;
    }
    const first = element.createChild('div', 'first-part');
    first.textContent = text.substring(0, splitPosition);
    const second = element.createChild('div', 'second-part');
    second.textContent = text.substring(splitPosition);
    element.title = text;
  }

  /**
   * @override
   * @param {?number} itemIndex
   * @param {string} promptValue
   */
  selectItem(itemIndex, promptValue) {
    const parsedExpression = promptValue.trim().match(/^([^:]*)(:\d+)?(:\d+)?$/);
    if (!parsedExpression) {
      return;
    }

    let lineNumber;
    let columnNumber;
    if (parsedExpression[2]) {
      lineNumber = parseInt(parsedExpression[2].substr(1), 10) - 1;
    }
    if (parsedExpression[3]) {
      columnNumber = parseInt(parsedExpression[3].substr(1), 10) - 1;
    }
    const uiSourceCode = itemIndex !== null ? this._uiSourceCodes[itemIndex] : null;
    this.uiSourceCodeSelected(uiSourceCode, lineNumber, columnNumber);
  }

  /**
   * @override
   * @param {string} query
   * @return {string}
   */
  rewriteQuery(query) {
    query = query ? query.trim() : '';
    if (!query || query === ':') {
      return '';
    }
    const lineNumberMatch = query.match(/^([^:]+)((?::[^:]*){0,2})$/);
    this._queryLineNumberAndColumnNumber = lineNumberMatch ? lineNumberMatch[2] : '';
    return lineNumberMatch ? lineNumberMatch[1] : query;
  }

  /**
   * @param {!Common.Event} event
   */
  _uiSourceCodeAdded(event) {
    const uiSourceCode = /** @type {!Workspace.UISourceCode} */ (event.data);
    if (!this._filterUISourceCode(uiSourceCode) || !this.filterProject(uiSourceCode.project())) {
      return;
    }
    this._uiSourceCodes.push(uiSourceCode);
    this.refresh();
  }

  /**
   * @override
   * @return {string}
   */
  notFoundText() {
    return Common.UIString('No files found');
  }

  /**
   * @override
   */
  attach() {
    Workspace.workspace.addEventListener(Workspace.Workspace.Events.UISourceCodeAdded, this._uiSourceCodeAdded, this);
    Workspace.workspace.addEventListener(Workspace.Workspace.Events.ProjectRemoved, this._projectRemoved, this);
    this._populate();
  }

  /**
   * @override
   */
  detach() {
    Workspace.workspace.removeEventListener(
        Workspace.Workspace.Events.UISourceCodeAdded, this._uiSourceCodeAdded, this);
    Workspace.workspace.removeEventListener(Workspace.Workspace.Events.ProjectRemoved, this._projectRemoved, this);
    this._queryLineNumberAndColumnNumber = '';
    this._defaultScores = null;
  }
};
