/*
 * Copyright (C) 2006, 2007, 2008 Apple Inc.  All rights reserved.
 * Copyright (C) 2007 Matt Lilek (pewtermoose@gmail.com).
 * Copyright (C) 2009 Joseph Pecoraro
 * Copyright (C) 2011 Google Inc. All rights reserved.
 *
 * 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.
 */

/**
 * @unrestricted
 */
export default class SearchableView extends UI.VBox {
  /**
   * @param {!Searchable} searchable
   * @param {string=} settingName
   */
  constructor(searchable, settingName) {
    super(true);
    this.registerRequiredCSS('ui/searchableView.css');
    this.element[_symbol] = this;

    this._searchProvider = searchable;
    this._setting = settingName ? Common.settings.createSetting(settingName, {}) : null;
    this._replaceable = false;

    this.contentElement.createChild('slot');
    this._footerElementContainer = this.contentElement.createChild('div', 'search-bar hidden');
    this._footerElementContainer.style.order = 100;
    this._footerElement = this._footerElementContainer.createChild('div', 'toolbar-search');

    const replaceToggleToolbar = new UI.Toolbar('replace-toggle-toolbar', this._footerElement);
    this._replaceToggleButton = new UI.ToolbarToggle(Common.UIString('Replace'), 'mediumicon-replace');
    this._replaceToggleButton.addEventListener(UI.ToolbarButton.Events.Click, this._toggleReplace, this);
    replaceToggleToolbar.appendToolbarItem(this._replaceToggleButton);

    const searchInputElements = this._footerElement.createChild('div', 'toolbar-search-inputs');
    const searchControlElement = searchInputElements.createChild('div', 'toolbar-search-control');

    this._searchInputElement = UI.HistoryInput.create();
    this._searchInputElement.classList.add('search-replace');
    this._searchInputElement.id = 'search-input-field';
    this._searchInputElement.placeholder = Common.UIString('Find');
    searchControlElement.appendChild(this._searchInputElement);

    this._matchesElement = searchControlElement.createChild('label', 'search-results-matches');
    this._matchesElement.setAttribute('for', 'search-input-field');

    const searchNavigationElement = searchControlElement.createChild('div', 'toolbar-search-navigation-controls');

    this._searchNavigationPrevElement =
        searchNavigationElement.createChild('div', 'toolbar-search-navigation toolbar-search-navigation-prev');
    this._searchNavigationPrevElement.addEventListener('click', this._onPrevButtonSearch.bind(this), false);
    this._searchNavigationPrevElement.title = Common.UIString('Search previous');

    this._searchNavigationNextElement =
        searchNavigationElement.createChild('div', 'toolbar-search-navigation toolbar-search-navigation-next');
    this._searchNavigationNextElement.addEventListener('click', this._onNextButtonSearch.bind(this), false);
    this._searchNavigationNextElement.title = Common.UIString('Search next');

    this._searchInputElement.addEventListener('keydown', this._onSearchKeyDown.bind(this), true);
    this._searchInputElement.addEventListener('input', this._onInput.bind(this), false);

    this._replaceInputElement =
        searchInputElements.createChild('input', 'search-replace toolbar-replace-control hidden');
    this._replaceInputElement.addEventListener('keydown', this._onReplaceKeyDown.bind(this), true);
    this._replaceInputElement.placeholder = Common.UIString('Replace');

    this._buttonsContainer = this._footerElement.createChild('div', 'toolbar-search-buttons');
    const firstRowButtons = this._buttonsContainer.createChild('div', 'first-row-buttons');

    const toolbar = new UI.Toolbar('toolbar-search-options', firstRowButtons);

    if (this._searchProvider.supportsCaseSensitiveSearch()) {
      this._caseSensitiveButton = new UI.ToolbarToggle(Common.UIString('Match Case'));
      this._caseSensitiveButton.setText('Aa');
      this._caseSensitiveButton.addEventListener(UI.ToolbarButton.Events.Click, this._toggleCaseSensitiveSearch, this);
      toolbar.appendToolbarItem(this._caseSensitiveButton);
    }

    if (this._searchProvider.supportsRegexSearch()) {
      this._regexButton = new UI.ToolbarToggle(Common.UIString('Use Regular Expression'));
      this._regexButton.setText('.*');
      this._regexButton.addEventListener(UI.ToolbarButton.Events.Click, this._toggleRegexSearch, this);
      toolbar.appendToolbarItem(this._regexButton);
    }

    const cancelButtonElement =
        UI.createTextButton(Common.UIString('Cancel'), this.closeSearch.bind(this), 'search-action-button');
    firstRowButtons.appendChild(cancelButtonElement);

    this._secondRowButtons = this._buttonsContainer.createChild('div', 'second-row-buttons hidden');

    this._replaceButtonElement =
        UI.createTextButton(Common.UIString('Replace'), this._replace.bind(this), 'search-action-button');
    this._replaceButtonElement.disabled = true;
    this._secondRowButtons.appendChild(this._replaceButtonElement);

    this._replaceAllButtonElement =
        UI.createTextButton(Common.UIString('Replace all'), this._replaceAll.bind(this), 'search-action-button');
    this._secondRowButtons.appendChild(this._replaceAllButtonElement);
    this._replaceAllButtonElement.disabled = true;

    this._minimalSearchQuerySize = 3;
    this._loadSetting();
  }

  /**
   * @param {?Element} element
   * @return {?SearchableView}
   */
  static fromElement(element) {
    let view = null;
    while (element && !view) {
      view = element[_symbol];
      element = element.parentElementOrShadowHost();
    }
    return view;
  }

  _toggleCaseSensitiveSearch() {
    this._caseSensitiveButton.setToggled(!this._caseSensitiveButton.toggled());
    this._saveSetting();
    this._performSearch(false, true);
  }

  _toggleRegexSearch() {
    this._regexButton.setToggled(!this._regexButton.toggled());
    this._saveSetting();
    this._performSearch(false, true);
  }

  _toggleReplace() {
    this._replaceToggleButton.setToggled(!this._replaceToggleButton.toggled());
    this._updateSecondRowVisibility();
  }

  _saveSetting() {
    if (!this._setting) {
      return;
    }
    const settingValue = this._setting.get() || {};
    settingValue.caseSensitive = this._caseSensitiveButton.toggled();
    settingValue.isRegex = this._regexButton.toggled();
    this._setting.set(settingValue);
  }

  _loadSetting() {
    const settingValue = this._setting ? (this._setting.get() || {}) : {};
    if (this._searchProvider.supportsCaseSensitiveSearch()) {
      this._caseSensitiveButton.setToggled(!!settingValue.caseSensitive);
    }
    if (this._searchProvider.supportsRegexSearch()) {
      this._regexButton.setToggled(!!settingValue.isRegex);
    }
  }

  /**
   * @param {number} minimalSearchQuerySize
   */
  setMinimalSearchQuerySize(minimalSearchQuerySize) {
    this._minimalSearchQuerySize = minimalSearchQuerySize;
  }

  /**
   * @param {string} placeholder
   */
  setPlaceholder(placeholder) {
    this._searchInputElement.placeholder = placeholder;
  }

  /**
   * @param {boolean} replaceable
   */
  setReplaceable(replaceable) {
    this._replaceable = replaceable;
  }

  /**
   * @param {number} matches
   * @suppress {checkTypes}
   */
  updateSearchMatchesCount(matches) {
    if (this._searchProvider.currentSearchMatches === matches) {
      return;
    }
    this._searchProvider.currentSearchMatches = matches;
    this._updateSearchMatchesCountAndCurrentMatchIndex(this._searchProvider.currentQuery ? matches : 0, -1);
  }

  /**
   * @param {number} currentMatchIndex
   * @suppress {checkTypes}
   */
  updateCurrentMatchIndex(currentMatchIndex) {
    this._updateSearchMatchesCountAndCurrentMatchIndex(this._searchProvider.currentSearchMatches, currentMatchIndex);
  }

  /**
   * @return {boolean}
   */
  isSearchVisible() {
    return this._searchIsVisible;
  }

  closeSearch() {
    this.cancelSearch();
    if (this._footerElementContainer.hasFocus()) {
      this.focus();
    }
  }

  _toggleSearchBar(toggled) {
    this._footerElementContainer.classList.toggle('hidden', !toggled);
    this.doResize();
  }

  cancelSearch() {
    if (!this._searchIsVisible) {
      return;
    }
    this.resetSearch();
    delete this._searchIsVisible;
    this._toggleSearchBar(false);
  }

  resetSearch() {
    this._clearSearch();
    this._updateReplaceVisibility();
    this._matchesElement.textContent = '';
  }

  refreshSearch() {
    if (!this._searchIsVisible) {
      return;
    }
    this.resetSearch();
    this._performSearch(false, false);
  }

  /**
   * @return {boolean}
   */
  handleFindNextShortcut() {
    if (!this._searchIsVisible) {
      return false;
    }
    this._searchProvider.jumpToNextSearchResult();
    return true;
  }

  /**
   * @return {boolean}
   */
  handleFindPreviousShortcut() {
    if (!this._searchIsVisible) {
      return false;
    }
    this._searchProvider.jumpToPreviousSearchResult();
    return true;
  }

  /**
   * @return {boolean}
   */
  handleFindShortcut() {
    this.showSearchField();
    return true;
  }

  /**
   * @return {boolean}
   */
  handleCancelSearchShortcut() {
    if (!this._searchIsVisible) {
      return false;
    }
    this.closeSearch();
    return true;
  }

  /**
   * @param {boolean} enabled
   */
  _updateSearchNavigationButtonState(enabled) {
    this._replaceButtonElement.disabled = !enabled;
    this._replaceAllButtonElement.disabled = !enabled;
    this._searchNavigationPrevElement.classList.toggle('enabled', enabled);
    this._searchNavigationNextElement.classList.toggle('enabled', enabled);
  }

  /**
   * @param {number} matches
   * @param {number} currentMatchIndex
   */
  _updateSearchMatchesCountAndCurrentMatchIndex(matches, currentMatchIndex) {
    if (!this._currentQuery) {
      this._matchesElement.textContent = '';
    } else if (matches === 0 || currentMatchIndex >= 0) {
      this._matchesElement.textContent = Common.UIString('%d of %d', currentMatchIndex + 1, matches);
    } else if (matches === 1) {
      this._matchesElement.textContent = Common.UIString('1 match');
    } else {
      this._matchesElement.textContent = Common.UIString('%d matches', matches);
    }
    this._updateSearchNavigationButtonState(matches > 0);
  }

  showSearchField() {
    if (this._searchIsVisible) {
      this.cancelSearch();
    }

    let queryCandidate;
    if (!this._searchInputElement.hasFocus()) {
      const selection = UI.inspectorView.element.window().getSelection();
      if (selection.rangeCount) {
        queryCandidate = selection.toString().replace(/\r?\n.*/, '');
      }
    }

    this._toggleSearchBar(true);
    this._updateReplaceVisibility();
    if (queryCandidate) {
      this._searchInputElement.value = queryCandidate;
    }
    this._performSearch(false, false);
    this._searchInputElement.focus();
    this._searchInputElement.select();
    this._searchIsVisible = true;
  }

  _updateReplaceVisibility() {
    this._replaceToggleButton.setVisible(this._replaceable);
    if (!this._replaceable) {
      this._replaceToggleButton.setToggled(false);
      this._updateSecondRowVisibility();
    }
  }

  /**
   * @param {!Event} event
   */
  _onSearchKeyDown(event) {
    if (isEscKey(event)) {
      this.closeSearch();
      event.consume(true);
      return;
    }
    if (!isEnterKey(event)) {
      return;
    }

    if (!this._currentQuery) {
      this._performSearch(true, true, event.shiftKey);
    } else {
      this._jumpToNextSearchResult(event.shiftKey);
    }
  }

  /**
   * @param {!Event} event
   */
  _onReplaceKeyDown(event) {
    if (isEnterKey(event)) {
      this._replace();
    }
  }

  /**
   * @param {boolean=} isBackwardSearch
   */
  _jumpToNextSearchResult(isBackwardSearch) {
    if (!this._currentQuery) {
      return;
    }

    if (isBackwardSearch) {
      this._searchProvider.jumpToPreviousSearchResult();
    } else {
      this._searchProvider.jumpToNextSearchResult();
    }
  }

  _onNextButtonSearch(event) {
    if (!this._searchNavigationNextElement.classList.contains('enabled')) {
      return;
    }
    this._jumpToNextSearchResult();
    this._searchInputElement.focus();
  }

  _onPrevButtonSearch(event) {
    if (!this._searchNavigationPrevElement.classList.contains('enabled')) {
      return;
    }
    this._jumpToNextSearchResult(true);
    this._searchInputElement.focus();
  }

  _onFindClick(event) {
    if (!this._currentQuery) {
      this._performSearch(true, true);
    } else {
      this._jumpToNextSearchResult();
    }
    this._searchInputElement.focus();
  }

  _onPreviousClick(event) {
    if (!this._currentQuery) {
      this._performSearch(true, true, true);
    } else {
      this._jumpToNextSearchResult(true);
    }
    this._searchInputElement.focus();
  }

  /** @suppress {checkTypes} */
  _clearSearch() {
    delete this._currentQuery;
    if (!!this._searchProvider.currentQuery) {
      delete this._searchProvider.currentQuery;
      this._searchProvider.searchCanceled();
    }
    this._updateSearchMatchesCountAndCurrentMatchIndex(0, -1);
  }

  /**
   * @param {boolean} forceSearch
   * @param {boolean} shouldJump
   * @param {boolean=} jumpBackwards
   * @suppress {checkTypes}
   */
  _performSearch(forceSearch, shouldJump, jumpBackwards) {
    const query = this._searchInputElement.value;
    if (!query || (!forceSearch && query.length < this._minimalSearchQuerySize && !this._currentQuery)) {
      this._clearSearch();
      return;
    }

    this._currentQuery = query;
    this._searchProvider.currentQuery = query;

    const searchConfig = this._currentSearchConfig();
    this._searchProvider.performSearch(searchConfig, shouldJump, jumpBackwards);
  }

  /**
   * @return {!SearchConfig}
   */
  _currentSearchConfig() {
    const query = this._searchInputElement.value;
    const caseSensitive = this._caseSensitiveButton ? this._caseSensitiveButton.toggled() : false;
    const isRegex = this._regexButton ? this._regexButton.toggled() : false;
    return new SearchConfig(query, caseSensitive, isRegex);
  }

  _updateSecondRowVisibility() {
    const secondRowVisible = this._replaceToggleButton.toggled();
    this._footerElementContainer.classList.toggle('replaceable', secondRowVisible);
    this._secondRowButtons.classList.toggle('hidden', !secondRowVisible);
    this._replaceInputElement.classList.toggle('hidden', !secondRowVisible);

    if (secondRowVisible) {
      this._replaceInputElement.focus();
    } else {
      this._searchInputElement.focus();
    }
    this.doResize();
  }

  _replace() {
    const searchConfig = this._currentSearchConfig();
    /** @type {!UI.Replaceable} */ (this._searchProvider)
        .replaceSelectionWith(searchConfig, this._replaceInputElement.value);
    delete this._currentQuery;
    this._performSearch(true, true);
  }

  _replaceAll() {
    const searchConfig = this._currentSearchConfig();
    /** @type {!UI.Replaceable} */ (this._searchProvider).replaceAllWith(searchConfig, this._replaceInputElement.value);
  }

  /**
   * @param {!Event} event
   */
  _onInput(event) {
    if (this._valueChangedTimeoutId) {
      clearTimeout(this._valueChangedTimeoutId);
    }
    const timeout = this._searchInputElement.value.length < 3 ? 200 : 0;
    this._valueChangedTimeoutId = setTimeout(this._onValueChanged.bind(this), timeout);
  }

  _onValueChanged() {
    if (!this._searchIsVisible) {
      return;
    }
    delete this._valueChangedTimeoutId;
    this._performSearch(false, true);
  }
}

export const _symbol = Symbol('searchableView');


/**
 * @interface
 */
export class Searchable {
  searchCanceled() {
  }

  /**
   * @param {!SearchConfig} searchConfig
   * @param {boolean} shouldJump
   * @param {boolean=} jumpBackwards
   */
  performSearch(searchConfig, shouldJump, jumpBackwards) {
  }

  jumpToNextSearchResult() {
  }

  jumpToPreviousSearchResult() {
  }

  /**
   * @return {boolean}
   */
  supportsCaseSensitiveSearch() {
  }

  /**
   * @return {boolean}
   */
  supportsRegexSearch() {}
}

/**
 * @interface
 */
export class Replaceable {
  /**
   * @param {!SearchConfig} searchConfig
   * @param {string} replacement
   */
  replaceSelectionWith(searchConfig, replacement) {
  }

  /**
   * @param {!SearchConfig} searchConfig
   * @param {string} replacement
   */
  replaceAllWith(searchConfig, replacement) {}
}

/**
 * @unrestricted
 */
export class SearchConfig {
  /**
   * @param {string} query
   * @param {boolean} caseSensitive
   * @param {boolean} isRegex
   */
  constructor(query, caseSensitive, isRegex) {
    this.query = query;
    this.caseSensitive = caseSensitive;
    this.isRegex = isRegex;
  }

  /**
   * @param {boolean=} global
   * @return {!RegExp}
   */
  toSearchRegex(global) {
    let modifiers = this.caseSensitive ? '' : 'i';
    if (global) {
      modifiers += 'g';
    }
    const query = this.isRegex ? '/' + this.query + '/' : this.query;

    let regex;

    // First try creating regex if user knows the / / hint.
    try {
      if (/^\/.+\/$/.test(query)) {
        regex = new RegExp(query.substring(1, query.length - 1), modifiers);
        regex.__fromRegExpQuery = true;
      }
    } catch (e) {
      // Silent catch.
    }

    // Otherwise just do a plain text search.
    if (!regex) {
      regex = createPlainTextSearchRegex(query, modifiers);
    }

    return regex;
  }
}

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

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

/** @constructor */
UI.SearchableView = SearchableView;

/**
 * @constructor
 */
UI.SearchableView.SearchConfig = SearchConfig;

/** @interface */
UI.Searchable = Searchable;

/** @interface */
UI.Replaceable = Replaceable;
