text: /* eslint-disable func-names, consistent-return, no-return-assign */
  
  import $ from 'jquery';
  import fuzzaldrinPlus from 'fuzzaldrin-plus';
  import { sanitize } from '~/lib/dompurify';
  import axios from '~/lib/utils/axios_utils';
  import { joinPaths, escapeFileUrl } from '~/lib/utils/url_utility';
  import { spriteIcon } from '~/lib/utils/common_utils';
  import { deprecatedCreateFlash as flash } from '~/flash';
  import { __ } from '~/locale';
  
  // highlight text(awefwbwgtc -> <b>a</b>wefw<b>b</b>wgt<b>c</b> )
  const highlighter = function(element, text, matches) {
    let j = 0;
    let len = 0;
    let lastIndex = 0;
    let matchedChars = [];
    let matchIndex = matches[j];
    let unmatched = text.substring(lastIndex, matchIndex);
    for (j = 0, len = matches.length; j < len; j += 1) {
      matchIndex = matches[j];
      unmatched = text.substring(lastIndex, matchIndex);
      if (unmatched) {
        if (matchedChars.length) {
          element.append(matchedChars.join('').bold());
        }
        matchedChars = [];
        element.append(document.createTextNode(unmatched));
      }
      matchedChars.push(text[matchIndex]);
      lastIndex = matchIndex + 1;
    }
    if (matchedChars.length) {
      element.append(matchedChars.join('').bold());
    }
    return element.append(document.createTextNode(text.substring(lastIndex)));
  };
  
  export default class ProjectFindFile {
    constructor(element1, options) {
      this.element = element1;
      this.options = options;
      this.goToBlob = this.goToBlob.bind(this);
      this.goToTree = this.goToTree.bind(this);
      this.selectRowDown = this.selectRowDown.bind(this);
      this.selectRowUp = this.selectRowUp.bind(this);
      this.filePaths = {};
      this.inputElement = this.element.find('.file-finder-input');
      // init event
      this.initEvent();
      // focus text input box
      this.inputElement.focus();
      // load file list
      this.load(this.options.url);
    }
  
    initEvent() {
      this.inputElement.off('keyup');
      this.inputElement.on('keyup', event => {
        const target = $(event.target);
        const value = target.val();
        const ref = target.data('oldValue');
        const oldValue = ref != null ? ref : '';
        if (value !== oldValue) {
          target.data('oldValue', value);
          this.findFile();
          return this.element
            .find('tr.tree-item')
            .eq(0)
            .addClass('selected')
            .focus();
        }
      });
    }
  
    findFile() {
      const searchText = sanitize(this.inputElement.val());
      const result =
        searchText.length > 0 ? fuzzaldrinPlus.filter(this.filePaths, searchText) : this.filePaths;
      return this.renderList(result, searchText);
      // find file
    }
  
    // files paths load
    load(url) {
      axios
        .get(url)
        .then(({ data }) => {
          this.element.find('.loading').hide();
          this.filePaths = data;
          this.findFile();
          this.element
            .find('.files-slider tr.tree-item')
            .eq(0)
            .addClass('selected')
            .focus();
        })
        .catch(() => flash(__('An error occurred while loading filenames')));
    }
  
    // render result
    renderList(filePaths, searchText) {
      let i = 0;
      let len = 0;
      let matches = [];
      const results = [];
      this.element.find('.tree-table > tbody').empty();
      for (i = 0, len = filePaths.length; i < len; i += 1) {
        const filePath = filePaths[i];
        if (i === 20) {
          break;
        }
        if (searchText) {
          matches = fuzzaldrinPlus.match(filePath, searchText);
        }
        const blobItemUrl = joinPaths(this.options.blobUrlTemplate, escapeFileUrl(filePath));
        const html = ProjectFindFile.makeHtml(filePath, matches, blobItemUrl);
        results.push(this.element.find('.tree-table > tbody').append(html));
      }
  
      this.element.find('.empty-state').toggleClass('hidden', Boolean(results.length));
  
      return results;
    }
  
    // make tbody row html
    static makeHtml(filePath, matches, blobItemUrl) {
      const $tr = $(
        `<tr class='tree-item'><td class='tree-item-file-name link-container'><a>${spriteIcon(
          'doc-text',
          's16 vertical-align-middle gl-mr-1',
        )}<span class='str-truncated'></span></a></td></tr>`,
      );
      if (matches) {
        $tr
          .find('a')
          .replaceWith(highlighter($tr.find('a'), filePath, matches).attr('href', blobItemUrl));
      } else {
        $tr.find('a').attr('href', blobItemUrl);
        $tr.find('.str-truncated').text(filePath);
      }
      return $tr;
    }
  
    selectRow(type) {
      const rows = this.element.find('.files-slider tr.tree-item');
      let selectedRow = this.element.find('.files-slider tr.tree-item.selected');
      let next = selectedRow.prev();
      if (rows && rows.length > 0) {
        if (selectedRow && selectedRow.length > 0) {
          if (type === 'UP') {
            next = selectedRow.prev();
          } else if (type === 'DOWN') {
            next = selectedRow.next();
          }
          if (next.length > 0) {
            selectedRow.removeClass('selected');
            selectedRow = next;
          }
        } else {
          selectedRow = rows.eq(0);
        }
        return selectedRow.addClass('selected').focus();
      }
    }
  
    selectRowUp() {
      return this.selectRow('UP');
    }
  
    selectRowDown() {
      return this.selectRow('DOWN');
    }
  
    goToTree() {
      return (window.location.href = this.options.treeUrl);
    }
  
    goToBlob() {
      const $link = this.element.find('.tree-item.selected .tree-item-file-name a');
  
      if ($link.length) {
        $link.get(0).click();
      }
    }
  }
  