/*! sifter.js | https://github.com/orchidjs/sifter.js | Apache License (v2) */
import { escape_regex } from './utils.js';

// @ts-ignore TS2691 "An import path cannot end with a '.ts' extension"
// https://github.com/andrewrk/node-diacritics/blob/master/index.js
var latin_pat;
const accent_pat = '[\u0300-\u036F\u{b7}\u{2be}]'; // \u{2bc}

const accent_reg = new RegExp(accent_pat, 'gu');
var diacritic_patterns;
const latin_convert = {
  'æ': 'ae',
  'ⱥ': 'a',
  'ø': 'o'
};
const convert_pat = new RegExp(Object.keys(latin_convert).join('|'), 'gu');
const code_points = [[0, 65535]];
/**
 * Remove accents
 * via https://github.com/krisk/Fuse/issues/133#issuecomment-318692703
 *
 */

const asciifold = str => {
  return str.normalize('NFKD').replace(accent_reg, '').toLowerCase().replace(convert_pat, function (foreignletter) {
    return latin_convert[foreignletter] || foreignletter;
  });
};
/**
 * Convert array of strings to a regular expression
 *	ex ['ab','a'] => (?:ab|a)
 * 	ex ['a','b'] => [ab]
 *
 */

const arrayToPattern = (chars, glue = '|') => {
  if (chars.length === 1 && chars[0] != undefined) {
    return chars[0];
  }

  var longest = 1;
  chars.forEach(a => {
    longest = Math.max(longest, a.length);
  });

  if (longest == 1) {
    return '[' + chars.join('') + ']';
  }

  return '(?:' + chars.join(glue) + ')';
};
const escapeToPattern = chars => {
  const escaped = chars.map(diacritic => escape_regex(diacritic));
  return arrayToPattern(escaped);
};
/**
 * Get all possible combinations of substrings that add up to the given string
 * https://stackoverflow.com/questions/30169587/find-all-the-combination-of-substrings-that-add-up-to-the-given-string
 *
 */

const allSubstrings = input => {
  if (input.length === 1) return [[input]];
  var result = [];
  allSubstrings(input.substring(1)).forEach(function (subresult) {
    var tmp = subresult.slice(0);
    tmp[0] = input.charAt(0) + tmp[0];
    result.push(tmp);
    tmp = subresult.slice(0);
    tmp.unshift(input.charAt(0));
    result.push(tmp);
  });
  return result;
};
/**
 * Generate a list of diacritics from the list of code points
 *
 */

const generateDiacritics = code_points => {
  var diacritics = {};
  code_points.forEach(code_range => {
    for (let i = code_range[0]; i <= code_range[1]; i++) {
      let diacritic = String.fromCharCode(i);
      let latin = asciifold(diacritic);

      if (latin == diacritic.toLowerCase()) {
        continue;
      } // skip when latin is a string longer than 3 characters long
      // bc the resulting regex patterns will be long
      // eg:
      // latin صلى الله عليه وسلم length 18 code point 65018
      // latin جل جلاله length 8 code point 65019


      if (latin.length > 3) {
        continue;
      }

      const latin_diacritics = diacritics[latin] || [latin];
      const patt = new RegExp(escapeToPattern(latin_diacritics), 'iu');

      if (diacritic.match(patt)) {
        continue;
      }

      latin_diacritics.push(diacritic);
      diacritics[latin] = latin_diacritics;
    }
  }); // filter out if there's only one character in the list
  // todo: this may not be needed

  Object.keys(diacritics).forEach(latin => {
    const latin_diacritics = diacritics[latin] || [];

    if (latin_diacritics.length < 2) {
      delete diacritics[latin];
    }
  }); // latin character pattern
  // match longer substrings first

  let latin_chars = Object.keys(diacritics).sort((a, b) => b.length - a.length);
  latin_pat = new RegExp('(' + escapeToPattern(latin_chars) + accent_pat + '*)', 'gu'); // build diacritic patterns
  // ae needs:
  //	(?:(?:ae|Æ|Ǽ|Ǣ)|(?:A|Ⓐ|Ａ...)(?:E|ɛ|Ⓔ...))

  var diacritic_patterns = {};
  latin_chars.sort((a, b) => a.length - b.length).forEach(latin => {
    var substrings = allSubstrings(latin);
    var pattern = substrings.map(sub_pat => {
      sub_pat = sub_pat.map(l => {
        if (diacritics.hasOwnProperty(l)) {
          return escapeToPattern(diacritics[l]);
        }

        return l;
      });
      return arrayToPattern(sub_pat, '');
    });
    diacritic_patterns[latin] = arrayToPattern(pattern);
  });
  return diacritic_patterns;
};
/**
 * Expand a regular expression pattern to include diacritics
 * 	eg /a/ becomes /aⓐａẚàáâầấẫẩãāăằắẵẳȧǡäǟảåǻǎȁȃạậặḁąⱥɐɑAⒶＡÀÁÂẦẤẪẨÃĀĂẰẮẴẲȦǠÄǞẢÅǺǍȀȂẠẬẶḀĄȺⱯ/
 *
 */

const diacriticRegexPoints = regex => {
  if (diacritic_patterns === undefined) {
    diacritic_patterns = generateDiacritics(code_points);
  }

  const decomposed = regex.normalize('NFKD').toLowerCase();
  return decomposed.split(latin_pat).map(part => {
    // "ﬄ" or "ffl"
    const no_accent = asciifold(part);

    if (no_accent == '') {
      return '';
    }

    if (diacritic_patterns.hasOwnProperty(no_accent)) {
      return diacritic_patterns[no_accent];
    }

    return part;
  }).join('');
};

export { allSubstrings, arrayToPattern, asciifold, diacriticRegexPoints, escapeToPattern, generateDiacritics };
//# sourceMappingURL=diacritics.js.map
