//= require lunr.min //= require _vendor/jquery.mark.js (function($, Modules) {

'use strict';

Modules.Search = function Search() {
  var s = this;
  var $html = $('html');
  s.lunrIndex;
  s.lunrData;
  var $searchForm;
  var $searchLabel;
  var $searchInput;
  var $searchResults;
  var $searchResultsTitle;
  var $searchResultsWrapper;
  var $searchResultsClose;
  var results;
  var query;
  var queryTimer;
  var maxSearchEntries = 20;

  this.start = function start($element) {
    $searchForm = $element.find('form');
    $searchInput = $element.find('#search');
    $searchLabel = $element.find('.search__label');
    $searchResultsWrapper = $element.find('.search-results')
    $searchResults = $searchResultsWrapper.find('.search-results__content');
    $searchResultsTitle = $searchResultsWrapper.find('.search-results__title');
    $searchResultsClose = $searchResultsWrapper.find('.search-results__close');
    s.downloadSearchIndex();
    attach();
    changeSearchLabel();
  };

  this.downloadSearchIndex = function downloadSearchIndex() {
    updateTitle('Loading search index')
    $.ajax({
      url: '/search.json',
      cache: true,
      method: 'GET',
      success: function(data) {
        s.lunrData = data;
        s.lunrIndex = lunr.Index.load(s.lunrData.index);
        replaceStopWordFilter();
        $(document).trigger('lunrIndexLoaded');
      }
    });
  }

  function attach() {
    // Search functionality on search text input
    $searchInput.on('input', function (e) {
      e.preventDefault();
      query = $(this).val();
      s.search(query, function(r) {
        results = r;
        renderResults(query);
        updateTitle();
      });
      if(window.ga) {
        window.clearTimeout(queryTimer);
        queryTimer = window.setTimeout(sendQueryToAnalytics, 1000);
      }
    });

    // Set focus on the first search result instead of submiting the search
    // form to Google
    $searchForm.on('submit', function(e) {
      e.preventDefault();
      showResults();
      $searchResults.find('.search-result__title a').first().focus();
    });

    // Closing the search results, move focus back to the search input
    $searchResultsClose.on('click', function(e) {
      e.preventDefault();
      $searchInput.focus();
      hideResults();
    });

    // Attach analytics events to search result clicks
    if(window.ga) {
      $searchResults.on('click', '.search-result__title a', function() {
        var href = $(this).attr('href');
        ga('send', {
          hitType: 'event',
          eventCategory: 'Search result',
          eventAction: 'click',
          eventLabel: href,
          transport: 'beacon'
        });
      });
    }

    // When selecting navigation link, close the search results.
    $('.toc').on('click','a', function(e) {
      hideResults();
    })
  }

  function changeSearchLabel() {
    $searchLabel.text('Search');
  }

  function getResults(query) {
    var results = [];
    s.lunrIndex.search(query).forEach( function (item, index) {
      if ( index < maxSearchEntries ) {
        results.push(s.lunrData.docs[item.ref]);
      }
    });
    return results;
  }

  this.search = function search(query, callback) {
    if(query === '') {
      hideResults();
      return;
    }
    showResults();
    // The index has not been downloaded yet, exit early and wait.
    if(!s.lunrIndex) {
      $(document).on('lunrIndexLoaded', function() {
        s.search(query, callback);
      });
      return;
    }
    callback(getResults(query));
  }

  function renderResults(query) {
    var output = '';
    if (results.length == 0) {
      output += '<p>Nothing found</p>';
    }
    output += '<ul>';
    for(var index in results) {
      var result = results[index];
      var content = s.processContent(result.content, query);
      output += '<li class="search-result">';
      output += '<h3 class="search-result__title">';
      output += '<a href="' + result.url + '">';
      output += result.title;
      output += '</a>';
      output += '</h3>';
      if(typeof content !== 'undefined') {
        output += '<p>' + content + '</p>';
      }
      output += '</li>';
    }
    output += '</ul>';

    $searchResults.html( output );
  }

  this.processContent = function processContent(content, query) {
    var output;
    content = '<div>'+  content + '</div>';
    content = $(content).mark(query);

    // Split content by sentence.
    var sentences = content.html().replace(/(\.+|\:|\!|\?|\r|\n)(\"*|\'*|\)*|}*|]*)/gm, "|").split("|");

    // Select the first five sentences that contain a <mark>
    var selectedSentences = [];
    for (var i = 0; i < sentences.length; i++) {
      if(selectedSentences.length === 5) {
        break;
      }

      var sentence = sentences[i].trim();
      var containsMark = sentence.includes('mark>');
      if (containsMark && (selectedSentences.indexOf(sentence) == -1)) {
        selectedSentences.push(sentence);
      }
    }
    if(selectedSentences.length > 0) {
      output = ' … ' + selectedSentences.join(' … ') + ' … ';
    }
    return output;
  }

  // Default text is to display the number of search results
  function updateTitle(text) {
    if(typeof text == "undefined") {
      var count = results.length;
      var text = count + ' results';
    }
    $searchResultsTitle.text(text);
  }

  function showResults() {
    $searchResultsWrapper.addClass('is-open')
    .attr('aria-hidden', 'false');
    $html.addClass('has-search-results-open');
  }

  function hideResults() {
    $searchResultsWrapper.removeClass('is-open')
    .attr('aria-hidden', 'true');
    $html.removeClass('has-search-results-open');
  }

  function sendQueryToAnalytics() {
    if(query === '') {
      return;
    }
    var stripped = window.stripPIIFromString(query)
    ga('send', {
      hitType: 'event',
      eventCategory: 'Search query',
      eventAction: 'type',
      eventLabel: stripped,
      transport: 'beacon'
    });
  }

  function replaceStopWordFilter() {
    // Replace the default stopWordFilter as it excludes useful words like
    // 'get'
    // See: https://lunrjs.com/docs/stop_word_filter.js.html#line43
    s.lunrIndex.pipeline.remove(lunr.stopWordFilter);
    s.lunrIndex.pipeline.add(s.govukStopWorldFilter);
  }

 this.govukStopWorldFilter = lunr.generateStopWordFilter([
    'a',
    'able',
    'about',
    'across',
    'after',
    'all',
    'almost',
    'also',
    'am',
    'among',
    'an',
    'and',
    'any',
    'are',
    'as',
    'at',
    'be',
    'because',
    'been',
    'but',
    'by',
    'can',
    'cannot',
    'could',
    'dear',
    'did',
    'do',
    'does',
    'either',
    'else',
    'ever',
    'every',
    'for',
    'from',
    'got',
    'had',
    'has',
    'have',
    'he',
    'her',
    'hers',
    'him',
    'his',
    'how',
    'however',
    'i',
    'if',
    'in',
    'into',
    'is',
    'it',
    'its',
    'just',
    'least',
    'let',
    'like',
    'likely',
    'may',
    'me',
    'might',
    'most',
    'must',
    'my',
    'neither',
    'no',
    'nor',
    'not',
    'of',
    'off',
    'often',
    'on',
    'only',
    'or',
    'other',
    'our',
    'own',
    'rather',
    'said',
    'say',
    'says',
    'she',
    'should',
    'since',
    'so',
    'some',
    'than',
    'that',
    'the',
    'their',
    'them',
    'then',
    'there',
    'these',
    'they',
    'this',
    'tis',
    'to',
    'too',
    'twas',
    'us',
    'wants',
    'was',
    'we',
    'were',
    'what',
    'when',
    'where',
    'which',
    'while',
    'who',
    'whom',
    'why',
    'will',
    'with',
    'would',
    'yet',
    'you',
    'your'
  ])
};

// Polyfill includes
if (!String.prototype.includes) {
  String.prototype.includes = function(search, start) {
    'use strict';
    if (typeof start !== 'number') {
      start = 0;
    }

    if (start + search.length > this.length) {
      return false;
    } else {
      return this.indexOf(search, start) !== -1;
    }
  };
}

})(jQuery, window.GOVUK.Modules);