/* eslint-disable no-param-reassign */
function startsWith(string: string, target: string, position: number = 0) {
  const { length } = string;
  if (position < 0) {
    position = 0;
  } else if (position > length) {
    position = length;
  }
  target = `${target}`;
  // eslint-disable-next-line eqeqeq
  return string.slice(position, position + target.length) == target;
}

function getBrowserLang() {
  if (typeof window === 'undefined') {
    return null;
  }

  const lang: string =
    (window.navigator.languages && window.navigator.languages[0]) ||
    window.navigator.language ||
    // @ts-expect-error
    window.navigator.browserLanguage ||
    // @ts-expect-error
    window.navigator.userLanguage ||
    // @ts-expect-error
    window.navigator.systemLanguage ||
    null;

  return lang;
}

function normalizeCode(code?: string | null) {
  return (code || '').toLowerCase().replace(/-/, '_');
}

function getPreferredLanguage(options?: { languages?: string[]; fallback: string }) {
  if (!options) {
    return getBrowserLang();
  }

  const { languages, fallback } = options;
  if (!options.languages) {
    return fallback;
  }

  // some browsers report language as en-US instead of en_US
  const browserLanguage = normalizeCode(getBrowserLang());

  if (!browserLanguage) {
    return fallback;
  }

  const match = languages!.filter((lang) => normalizeCode(lang) === browserLanguage);

  if (match.length > 0) {
    return match[0] || fallback;
  }

  // en == en_US
  const matchCodeOnly = languages!.filter((lang) => startsWith(browserLanguage, lang));
  return matchCodeOnly[0] || fallback;
}

export default getPreferredLanguage;
