﻿SearchView = function(searchValueInput, searchButton, inTitlesOnlyCheckbox, highlightCheckbox, searchResultsCounter, searchResultsContainer) {
  this.searchValueInput = searchValueInput;
  this.searchButton = searchButton;
  this.inTitlesOnlyCheckbox = inTitlesOnlyCheckbox;
  this.highlightCheckbox = highlightCheckbox;
  this.searchResultsCounter = searchResultsCounter;
  this.searchResultsContainer = searchResultsContainer;

  $(this.searchButton).bind("click", this, this.onSearchButtonClick);
  $(this.highlightCheckbox).bind("click", this, this.onHighlightClick);

  if ($.browser.opera)
    $(this.searchValueInput).bind("keypress", this, this.onKeydown);
  else
    $(this.searchValueInput).bind("keydown", this, this.onKeydown);

  if ($.browser.opera)
    $(this.searchValueInput).bind(
      "keypress", this,
      function(event) { if (event.keyCode == 9) event.preventDefault(); });

  if ($.browser.opera)
    $(this.searchButton).bind("keypress", this, this.onSearchButtonKeydown);
  else
    $(this.searchButton).bind("keydown", this, this.onSearchButtonKeydown);

  if ($.browser.opera)
    $(this.searchButton).bind(
      "keypress", this,
      function(event) { if (event.keyCode == 9) event.preventDefault(); });

  var eventName = $.browser.opera ? "keypress" : "keydown";

  $(this.inTitlesOnlyCheckbox).bind(eventName, this, this.onTitlesCheckboxKeydown);
  $(this.highlightCheckbox).bind(eventName, this, this.onHighlightCheckboxKeydown);
  $(this.searchResultsContainer).bind(eventName, this, this.onContainerKeydown);

  this.searchButton.disabled = true;
  $(this.searchResultsContainer).html(
    Resources.getInstance().pleaseWait + "<br/>" +
    "<a target='_blank' href='http://www.x-tensive.com/Products/HS/' title='" + Resources.getInstance().visitHelpServerPage + "'>Help Server</a> " + Resources.getInstance().isUpdatingTheIndexes + ".<br/>");

  this.checkIsBuilding();
}

SearchView.prototype = {
  originalInnerHTML: null,
  searchResultsClicked: false,
  highlightStartTag: "<span style='color:blue; background-color:yellow;'>",
  highlightEndTag: "</span>",
  lastSearchValue: null,
  currentItem: null,

  checkIsBuilding: function() {
    var searchView = this;
    Xtensive.HelpServer.Web.SearchResultProvider.IsBuilding(function(isBuilding) {
      if (isBuilding)
        setTimeout(function() { searchView.checkIsBuilding(); }, 15000);
      else {
        searchView.searchButton.disabled = false;
        $(searchView.searchResultsContainer).empty();
      }
    });
  },

  search: function(value) {
    this.searchValueInput.value = value;
    $(this.searchResultsCounter).html(Resources.getInstance().noResultsFound);
    $(searchView.searchResultsContainer).empty();
    this.doSearch();
  },

  initialize: function() {
    try {
      this.searchValueInput.focus();
      if ($.browser.msie) {
        if (this.searchValueInput.createTextRange != null) {
          var r = this.searchValueInput.createTextRange();
          r.collapse(false);
          r.select();
        }
      }
      else {
        if (this.searchValueInput.selectionStart != null) {
          var end = this.searchValueInput.value.length;
          this.searchValueInput.setSelectionRange(end, end);
          this.searchValueInput.focus();
        }
      }
    }
    catch (e) { }
  },

  onHighlightCheckboxKeydown: function(event) {
    if (event.keyCode == 9) {
      var searchView = event.data;
      var currentItem = searchView.currentItem;
      if (currentItem == null) {
        var items = $(searchView.searchResultsContainer).find("a[searchItem='1']:first");
        if (items.length > 0)
          items[0].focus();
        else
          searchView.searchValueInput.focus();
      }
      else
        currentItem.focus();
      event.stopPropagation();
      event.preventDefault();
    }
  },

  onTitlesCheckboxKeydown: function(event) {
    if (event.keyCode == 9) {
      var searchView = event.data;
      searchView.highlightCheckbox.focus();
      event.stopPropagation();
      event.preventDefault();
    }
  },

  onKeydown: function(event) {
    var searchView = event.data;
    if (event.keyCode == 13) {
      event.stopPropagation();
      event.preventDefault();
      searchView.doSearch();
    }
    else if (event.keyCode == 9) {
      if (searchView.searchButton.disabled)
        searchView.inTitlesOnlyCheckbox.focus();
      else
        searchView.searchButton.focus();
      event.stopPropagation();
      event.preventDefault();
    }
  },

  onSearchButtonKeydown: function(event) {
    if (event.keyCode == 9) {
      var searchView = event.data;
      searchView.inTitlesOnlyCheckbox.focus();
      event.stopPropagation();
      event.preventDefault();
    }
  },

  onSearchButtonClick: function(event) {
    var searchView = event.data;
    searchView.doSearch();
  },

  doSearch: function() {
    var searchView = this;
    var searchValue = searchView.searchValueInput.value;
    if (searchValue == null || searchValue.length == 0)
      return;
    searchView.searchButton.disabled = true;
    Xtensive.HelpServer.Web.SearchResultProvider.Search(
      searchValue, searchView.inTitlesOnlyCheckbox.checked, function(result) {
        searchView.lastSearchValue = searchValue;
        var length = result.length;
        if (length > 0)
          $(searchView.searchResultsCounter).html(String.format(Resources.getInstance().resultsFound, length));
        else
          $(searchView.searchResultsCounter).html(Resources.getInstance().noResultsFound);
        $(searchView.searchResultsContainer).find("a").unbind();
        $(searchView.searchResultsContainer).empty();
        searchView.currentItem = null;
        var fistAnchor = null;
        for (var i = 0; i < length; i++) {
          var resultItem = result[i];
          var anchor = $("<a href='" + resultItem.Url + "' target='contentFrame' searchItem='1'>" + resultItem.Title + "</a>")[0];
          $(anchor).bind("click", anchor, function(event) { searchView.searchResultsClicked = true; event.data.focus(); });
          $(anchor).bind(
            "focus",
            anchor,
            function(event) {
              searchView.currentItem = event.data;
              $(searchView.searchResultsContainer).find("a[class*='ActiveSearchItem']").removeClass("ActiveSearchItem");
              $(searchView.currentItem).addClass("ActiveSearchItem");
            });
          $(searchView.searchResultsContainer).append(anchor);
          if (fistAnchor == null)
            fistAnchor = anchor;
        }
        if (fistAnchor != null)
          fistAnchor.focus();
        searchView.searchButton.disabled = false;
      },
      function(err) { alert(err._message); searchView.searchButton.disabled = false; });
  },

  onHighlightClick: function(event) {
    var searchView = event.data;
    if (!searchView.originalInnerHTML)
      return;

    try {
      var doc = GetContentFrame().contentWindow.document;
      var currentInnerHTML = doc.body.innerHTML;
      if (currentInnerHTML != searchView.originalInnerHTML) {
        doc.body.innerHTML = searchView.originalInnerHTML;
        searchView.originalInnerHTML = currentInnerHTML;
      }
    }
    catch (e) { }
  },

  onContentLoaded: function(doc, active) {
    this.originalInnerHTML = null;
    if (this.searchResultsClicked) {
      this.searchResultsClicked = false;
      this.processContent(doc);
    }
    if (active && this.currentItem != null)
      this.currentItem.focus();
  },

  processContent: function(doc) {
    try {
      this.originalInnerHTML = doc.body.innerHTML;
      this.highlight(doc);
    }
    catch (e) { }
  },

  highlight: function(doc) {
    var searchString = this.lastSearchValue;
    if (searchString != null && searchString.length != 0 && this.highlightCheckbox.checked)
      this.highlightSearchTerms(doc, searchString, false);
  },

  doHighlight: function(bodyText, searchTerm) {
    // find all occurences of the search term in the given text,
    // and add some "highlight" tags to them (we're not using a
    // regular expression search, because we want to filter out
    // matches that occur within HTML tags and script blocks, so
    // we have to do a little extra validation)
    var newText = "", c = "";
    var i = -1;
    var lcSearchTerm = searchTerm.toLowerCase();
    var lcBodyText = bodyText.toLowerCase();

    while (bodyText.length > 0) {
      i = lcBodyText.indexOf(lcSearchTerm, i + 1);
      if (i < 0) {
        newText += bodyText;
        bodyText = "";
      } else {
        // skip anything inside an HTML tag
        if (bodyText.lastIndexOf(">", i) >= bodyText.lastIndexOf("<", i)) {
          // skip anything inside a <script> block
          if (lcBodyText.lastIndexOf("/script>", i) >= lcBodyText.lastIndexOf("<script", i)) {
            // take only word beginnings into account
            c = i <= 0 ? " " : bodyText.substr(i - 1, 1);
            if (!((c >= "A" && c <= "Z") || (c >= "a" && c <= "z"))) {
              newText += bodyText.substring(0, i) + this.highlightStartTag + bodyText.substr(i, searchTerm.length) + this.highlightEndTag;
              bodyText = bodyText.substr(i + searchTerm.length);
              lcBodyText = bodyText.toLowerCase();
              i = -1;
            }
          }
        }
      }
    }

    return newText;
  },

  highlightSearchTerms: function(doc, searchText, treatAsPhrase) {
    if (treatAsPhrase)
      searchArray = [searchText];
    else
      searchArray = searchText.split(" ");

    if (!doc.body || typeof (doc.body.innerHTML) == "undefined") {
      return false;
    }

    var bodyText = doc.body.innerHTML;
    for (var i = 0; i < searchArray.length; i++) {
      if (searchArray[i] != "")
        bodyText = this.doHighlight(bodyText, searchArray[i]);
    }

    doc.body.innerHTML = bodyText;
    return true;
  },

  onContainerKeydown: function(event) {
    var searchView = event.data;
    if (event.keyCode == 40 || event.keyCode == 38) {
      // down || up
      var currentItem = searchView.currentItem;
      if (currentItem == null)
        $(searchView.searchResultsContainer).find("a[searchItem='1']:first").focus();
      else {
        if (event.keyCode == 40)
          $(currentItem).next("a[searchItem='1']").focus();
        else
          $(currentItem).prev("a[searchItem='1']").focus();
      }
      event.preventDefault();
    }
    else if (event.keyCode == 34 || event.keyCode == 33) {
      // pageDown|| pageUp
      var pageUp = event.keyCode == 33;
      var currentItem = searchView.currentItem;
      if (currentItem == null)
        $(searchView.searchResultsContainer).find("a[searchItem='1']:first").focus();
      else {
        var itemHeight = currentItem.scrollHeight;
        if (itemHeight != 0) {
          var containerHeight = searchView.searchResultsContainer.clientHeight;
          var toJump = Math.floor(containerHeight / itemHeight) - 2;
          if (toJump > 0) {
            var items;
            if (pageUp)
              items = $(currentItem).prevAll("a[searchItem='1']");
            else
              items = $(currentItem).nextAll("a[searchItem='1']");
            if (items.length > toJump)
              items[toJump].focus();
            else if (items.length > 0)
              items[items.length - 1].focus();
          }
        }
      }
      event.preventDefault();
    }
    else if (event.keyCode == 9) {
      searchView.searchValueInput.focus();
      event.stopPropagation();
      event.preventDefault();
    }
  }
}