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

cr.define('options', function() {
  /** @const */ var OptionsPage = options.OptionsPage;

  /**
   * Encapsulated handling of a search bubble.
   * @constructor
   */
  function SearchBubble(text) {
    var el = cr.doc.createElement('div');
    SearchBubble.decorate(el);
    el.content = text;
    return el;
  }

  SearchBubble.decorate = function(el) {
    el.__proto__ = SearchBubble.prototype;
    el.decorate();
  };

  SearchBubble.prototype = {
    __proto__: HTMLDivElement.prototype,

    decorate: function() {
      this.className = 'search-bubble';

      this.innards_ = cr.doc.createElement('div');
      this.innards_.className = 'search-bubble-innards';
      this.appendChild(this.innards_);

      // We create a timer to periodically update the position of the bubbles.
      // While this isn't all that desirable, it's the only sure-fire way of
      // making sure the bubbles stay in the correct location as sections
      // may dynamically change size at any time.
      this.intervalId = setInterval(this.updatePosition.bind(this), 250);
    },

    /**
     * Sets the text message in the bubble.
     * @param {string} text The text the bubble will show.
     */
    set content(text) {
      this.innards_.textContent = text;
    },

    /**
     * Attach the bubble to the element.
     */
    attachTo: function(element) {
      var parent = element.parentElement;
      if (!parent)
        return;
      if (parent.tagName == 'TD') {
        // To make absolute positioning work inside a table cell we need
        // to wrap the bubble div into another div with position:relative.
        // This only works properly if the element is the first child of the
        // table cell which is true for all options pages.
        this.wrapper = cr.doc.createElement('div');
        this.wrapper.className = 'search-bubble-wrapper';
        this.wrapper.appendChild(this);
        parent.insertBefore(this.wrapper, element);
      } else {
        parent.insertBefore(this, element);
      }
    },

    /**
     * Clear the interval timer and remove the element from the page.
     */
    dispose: function() {
      clearInterval(this.intervalId);

      var child = this.wrapper || this;
      var parent = child.parentNode;
      if (parent)
        parent.removeChild(child);
    },

    /**
     * Update the position of the bubble.  Called at creation time and then
     * periodically while the bubble remains visible.
     */
    updatePosition: function() {
      // This bubble is 'owned' by the next sibling.
      var owner = (this.wrapper || this).nextSibling;

      // If there isn't an offset parent, we have nothing to do.
      if (!owner.offsetParent)
        return;

      // Position the bubble below the location of the owner.
      var left = owner.offsetLeft + owner.offsetWidth / 2 -
          this.offsetWidth / 2;
      var top = owner.offsetTop + owner.offsetHeight;

      // Update the position in the CSS.  Cache the last values for
      // best performance.
      if (left != this.lastLeft) {
        this.style.left = left + 'px';
        this.lastLeft = left;
      }
      if (top != this.lastTop) {
        this.style.top = top + 'px';
        this.lastTop = top;
      }
    },
  };

  /**
   * Encapsulated handling of the search page.
   * @constructor
   */
  function SearchPage() {
    OptionsPage.call(this, 'search',
                     loadTimeData.getString('searchPageTabTitle'),
                     'searchPage');
  }

  cr.addSingletonGetter(SearchPage);

  SearchPage.prototype = {
    // Inherit SearchPage from OptionsPage.
    __proto__: OptionsPage.prototype,

    /**
     * A boolean to prevent recursion. Used by setSearchText_().
     * @type {boolean}
     * @private
     */
    insideSetSearchText_: false,

    /**
     * Initialize the page.
     */
    initializePage: function() {
      // Call base class implementation to start preference initialization.
      OptionsPage.prototype.initializePage.call(this);

      this.searchField = $('search-field');

      // Handle search events. (No need to throttle, WebKit's search field
      // will do that automatically.)
      this.searchField.onsearch = function(e) {
        this.setSearchText_(e.currentTarget.value);
      }.bind(this);

      // Install handler for key presses.
      document.addEventListener('keydown',
                                this.keyDownEventHandler_.bind(this));
    },

    /** @override */
    get sticky() {
      return true;
    },

    /**
     * Called after this page has shown.
     */
    didShowPage: function() {
      // This method is called by the Options page after all pages have
      // had their visibilty attribute set.  At this point we can perform the
      // search specific DOM manipulation.
      this.setSearchActive_(true);
    },

    /**
     * Called before this page will be hidden.
     */
    willHidePage: function() {
      // This method is called by the Options page before all pages have
      // their visibilty attribute set.  Before that happens, we need to
      // undo the search specific DOM manipulation that was performed in
      // didShowPage.
      this.setSearchActive_(false);
    },

    /**
     * Update the UI to reflect whether we are in a search state.
     * @param {boolean} active True if we are on the search page.
     * @private
     */
    setSearchActive_: function(active) {
      // It's fine to exit if search wasn't active and we're not going to
      // activate it now.
      if (!this.searchActive_ && !active)
        return;

      this.searchActive_ = active;

      if (active) {
        var hash = location.hash;
        if (hash) {
          if (this.searchField != document.activeElement) {
            this.searchField.value =
                decodeURIComponent(hash.slice(1).replace(/\+/g, ' '));
          }
        } else if (!this.searchField.value) {
          // This should only happen if the user goes directly to
          // chrome://settings-frame/search
          OptionsPage.showDefaultPage();
          return;
        }

        // Move 'advanced' sections into the main settings page to allow
        // searching.
        if (!this.advancedSections_) {
          this.advancedSections_ =
              $('advanced-settings-container').querySelectorAll('section');
          for (var i = 0, section; section = this.advancedSections_[i]; i++)
            $('settings').appendChild(section);
        }
      }

      var pagesToSearch = this.getSearchablePages_();
      for (var key in pagesToSearch) {
        var page = pagesToSearch[key];

        if (!active)
          page.visible = false;

        // Update the visible state of all top-level elements that are not
        // sections (ie titles, button strips).  We do this before changing
        // the page visibility to avoid excessive re-draw.
        for (var i = 0, childDiv; childDiv = page.pageDiv.children[i]; i++) {
          if (active) {
            if (childDiv.tagName != 'SECTION')
              childDiv.classList.add('search-hidden');
          } else {
            childDiv.classList.remove('search-hidden');
          }
        }

        if (active) {
          // When search is active, remove the 'hidden' tag.  This tag may have
          // been added by the OptionsPage.
          page.pageDiv.hidden = false;
        }
      }

      if (active) {
        this.setSearchText_(this.searchField.value);
        this.searchField.focus();
      } else {
        // After hiding all page content, remove any search results.
        this.unhighlightMatches_();
        this.removeSearchBubbles_();

        // Move 'advanced' sections back into their original container.
        if (this.advancedSections_) {
          for (var i = 0, section; section = this.advancedSections_[i]; i++)
            $('advanced-settings-container').appendChild(section);
          this.advancedSections_ = null;
        }
      }
    },

    /**
     * Set the current search criteria.
     * @param {string} text Search text.
     * @private
     */
    setSearchText_: function(text) {
      // Prevent recursive execution of this method.
      if (this.insideSetSearchText_) return;
      this.insideSetSearchText_ = true;

      // Cleanup the search query string.
      text = SearchPage.canonicalizeQuery(text);

      // Set the hash on the current page, and the enclosing uber page
      var hash = text ? '#' + encodeURIComponent(text) : '';
      var path = text ? this.name : '';
      window.location.hash = hash;
      uber.invokeMethodOnParent('setPath', {path: path + hash});

      // Toggle the search page if necessary.
      if (text) {
        if (!this.searchActive_)
          OptionsPage.showPageByName(this.name, false);
      } else {
        if (this.searchActive_)
          OptionsPage.showPageByName(OptionsPage.getDefaultPage().name, false);

        this.insideSetSearchText_ = false;
        return;
      }

      var foundMatches = false;

      // Remove any prior search results.
      this.unhighlightMatches_();
      this.removeSearchBubbles_();

      var pagesToSearch = this.getSearchablePages_();
      for (var key in pagesToSearch) {
        var page = pagesToSearch[key];
        var elements = page.pageDiv.querySelectorAll('section');
        for (var i = 0, node; node = elements[i]; i++) {
          node.classList.add('search-hidden');
        }
      }

      var bubbleControls = [];

      // Generate search text by applying lowercase and escaping any characters
      // that would be problematic for regular expressions.
      var searchText =
          text.toLowerCase().replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
      // Generate a regular expression for hilighting search terms.
      var regExp = new RegExp('(' + searchText + ')', 'ig');

      if (searchText.length) {
        // Search all top-level sections for anchored string matches.
        for (var key in pagesToSearch) {
          var page = pagesToSearch[key];
          var elements =
              page.pageDiv.querySelectorAll('section');
          for (var i = 0, node; node = elements[i]; i++) {
            if (this.highlightMatches_(regExp, node)) {
              node.classList.remove('search-hidden');
              if (!node.hidden)
                foundMatches = true;
            }
          }
        }

        // Search all sub-pages, generating an array of top-level sections that
        // we need to make visible.
        var subPagesToSearch = this.getSearchableSubPages_();
        var control, node;
        for (var key in subPagesToSearch) {
          var page = subPagesToSearch[key];
          if (this.highlightMatches_(regExp, page.pageDiv)) {
            this.revealAssociatedSections_(page);

            bubbleControls =
                bubbleControls.concat(this.getAssociatedControls_(page));

            foundMatches = true;
          }
        }
      }

      // Configure elements on the search results page based on search results.
      $('searchPageNoMatches').hidden = foundMatches;

      // Create search balloons for sub-page results.
      length = bubbleControls.length;
      for (var i = 0; i < length; i++)
        this.createSearchBubble_(bubbleControls[i], text);

      // Cleanup the recursion-prevention variable.
      this.insideSetSearchText_ = false;
    },

    /**
     * Reveal the associated section for |subpage|, as well as the one for its
     * |parentPage|, and its |parentPage|'s |parentPage|, etc.
     * @private
     */
    revealAssociatedSections_: function(subpage) {
      for (var page = subpage; page; page = page.parentPage) {
        var section = page.associatedSection;
        if (section)
          section.classList.remove('search-hidden');
      }
    },

    /**
     * @return {!Array.<HTMLElement>} all the associated controls for |subpage|,
     * including |subpage.associatedControls| as well as any controls on parent
     * pages that are indirectly necessary to get to the subpage.
     * @private
     */
    getAssociatedControls_: function(subpage) {
      var controls = [];
      for (var page = subpage; page; page = page.parentPage) {
        if (page.associatedControls)
          controls = controls.concat(page.associatedControls);
      }
      return controls;
    },

    /**
     * Wraps matches in spans.
     * @param {RegExp} regExp The search query (in regexp form).
     * @param {Element} element An HTML container element to recursively search
     *     within.
     * @return {boolean} true if the element was changed.
     * @private
     */
    highlightMatches_: function(regExp, element) {
      var found = false;
      var div, child, tmp;

      // Walk the tree, searching each TEXT node.
      var walker = document.createTreeWalker(element,
                                             NodeFilter.SHOW_TEXT,
                                             null,
                                             false);
      var node = walker.nextNode();
      while (node) {
        var textContent = node.nodeValue;
        // Perform a search and replace on the text node value.
        var split = textContent.split(regExp);
        if (split.length > 1) {
          found = true;
          var nextNode = walker.nextNode();
          var parentNode = node.parentNode;
          // Use existing node as placeholder to determine where to insert the
          // replacement content.
          for (var i = 0; i < split.length; ++i) {
            if (i % 2 == 0) {
              parentNode.insertBefore(document.createTextNode(split[i]), node);
            } else {
              var span = document.createElement('span');
              span.className = 'search-highlighted';
              span.textContent = split[i];
              parentNode.insertBefore(span, node);
            }
          }
          // Remove old node.
          parentNode.removeChild(node);
          node = nextNode;
        } else {
          node = walker.nextNode();
        }
      }

      return found;
    },

    /**
     * Removes all search highlight tags from the document.
     * @private
     */
    unhighlightMatches_: function() {
      // Find all search highlight elements.
      var elements = document.querySelectorAll('.search-highlighted');

      // For each element, remove the highlighting.
      var parent, i;
      for (var i = 0, node; node = elements[i]; i++) {
        parent = node.parentNode;

        // Replace the highlight element with the first child (the text node).
        parent.replaceChild(node.firstChild, node);

        // Normalize the parent so that multiple text nodes will be combined.
        parent.normalize();
      }
    },

    /**
     * Creates a search result bubble attached to an element.
     * @param {Element} element An HTML element, usually a button.
     * @param {string} text A string to show in the bubble.
     * @private
     */
    createSearchBubble_: function(element, text) {
      // avoid appending multiple bubbles to a button.
      var sibling = element.previousElementSibling;
      if (sibling && (sibling.classList.contains('search-bubble') ||
                      sibling.classList.contains('search-bubble-wrapper')))
        return;

      var parent = element.parentElement;
      if (parent) {
        var bubble = new SearchBubble(text);
        bubble.attachTo(element);
        bubble.updatePosition();
      }
    },

    /**
     * Removes all search match bubbles.
     * @private
     */
    removeSearchBubbles_: function() {
      var elements = document.querySelectorAll('.search-bubble');
      var length = elements.length;
      for (var i = 0; i < length; i++)
        elements[i].dispose();
    },

    /**
     * Builds a list of top-level pages to search.  Omits the search page and
     * all sub-pages.
     * @return {Array} An array of pages to search.
     * @private
     */
    getSearchablePages_: function() {
      var name, page, pages = [];
      for (name in OptionsPage.registeredPages) {
        if (name != this.name) {
          page = OptionsPage.registeredPages[name];
          if (!page.parentPage)
            pages.push(page);
        }
      }
      return pages;
    },

    /**
     * Builds a list of sub-pages (and overlay pages) to search.  Ignore pages
     * that have no associated controls.
     * @return {Array} An array of pages to search.
     * @private
     */
    getSearchableSubPages_: function() {
      var name, pageInfo, page, pages = [];
      for (name in OptionsPage.registeredPages) {
        page = OptionsPage.registeredPages[name];
        if (page.parentPage && page.associatedSection)
          pages.push(page);
      }
      for (name in OptionsPage.registeredOverlayPages) {
        page = OptionsPage.registeredOverlayPages[name];
        if (page.associatedSection && page.pageDiv != undefined)
          pages.push(page);
      }
      return pages;
    },

    /**
     * A function to handle key press events.
     * @return {Event} a keydown event.
     * @private
     */
    keyDownEventHandler_: function(event) {
      /** @const */ var ESCAPE_KEY_CODE = 27;
      /** @const */ var FORWARD_SLASH_KEY_CODE = 191;

      switch (event.keyCode) {
        case ESCAPE_KEY_CODE:
          if (event.target == this.searchField) {
            this.setSearchText_('');
            this.searchField.blur();
            event.stopPropagation();
            event.preventDefault();
          }
          break;
        case FORWARD_SLASH_KEY_CODE:
          if (!/INPUT|SELECT|BUTTON|TEXTAREA/.test(event.target.tagName) &&
              !event.ctrlKey && !event.altKey) {
            this.searchField.focus();
            event.stopPropagation();
            event.preventDefault();
          }
          break;
      }
    },
  };

  /**
   * Standardizes a user-entered text query by removing extra whitespace.
   * @param {string} The user-entered text.
   * @return {string} The trimmed query.
   */
  SearchPage.canonicalizeQuery = function(text) {
    // Trim beginning and ending whitespace.
    return text.replace(/^\s+|\s+$/g, '');
  };

  // Export
  return {
    SearchPage: SearchPage
  };

});
