import { autorun, makeAutoObservable } from 'mobx';
import { fromPromise, FULFILLED } from 'mobx-utils';
import { IntlConfig } from 'react-intl';

export const SupportedLocales = [
  'en-us',
  'pt-br'
  // "th-th",
  // "es-es",
  // "fr-fr",
  // "ko-kr",
];
export const localeBundles: Record<symbol, IntlConfig['messages']> = {
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
  //@ts-ignore
  'en-us': import('./en-us.json')
  // "pt-br": import("./strings/pt-br.json"),
  // "th-th": import("./strings/th-th.json"),
  // "es-es": import("./strings/es-es.json"),
  // "fr-fr": import("./strings/fr-fr.json"),
  // "ko-kr": import("./strings/ko-kr.json"),
};

interface OptionsType {
  value: string;
  label: string;
}
// Class to handle locales
const DEFAULT_LOCALE = 'en-us';

export class Locale {
  private defaultLocale: string;
  supportedLanguages: string[];
  locale: string;
  strings: any;

  constructor(defaultLocale?: string) {
    this.defaultLocale = defaultLocale || DEFAULT_LOCALE;
    this.locale = getSupportedLanguage();
    this.supportedLanguages = SupportedLocales;
    this.getStringsFromLocale(this.locale).then((messages) => {
      this.setStrings(messages);
    });

    makeAutoObservable(this);
  }

  get selectedLocale(): string {
    return this.locale;
  }

  get messages(): Record<symbol, IntlConfig['messages']> {
    return this.strings;
  }

  get supportedLanguagesList() {
    return this.supportedLanguages;
  }

  public getDefaultLocale = (): string => {
    return this.defaultLocale;
  };

  public getLocaleFromUrl = (userLocale?: string): string => {
    const pathname = window ? window?.location.pathname : '';
    const urlParams = pathname.split('/');
    const languageFromUrlParam =
      urlParams.length >= 2 ? urlParams[1] : undefined;
    const shouldOverwriteUserLocale = languageFromUrlParam !== userLocale;
    // url param will rewrite user preferences
    const loc = shouldOverwriteUserLocale ? languageFromUrlParam : userLocale;
    // check if the language is supported, otherwise display default locale
    const locale =
      loc && this.supportedLanguagesList.includes(loc) ? loc : DEFAULT_LOCALE;
    return locale;
  };

  setLocale = async (locale: string) => {
    const strings = await this.getStringsFromLocale(locale);
    this.setStrings(strings);
    this.locale = locale;
  };

  setStrings = (messages: any) => {
    this.strings = messages;
  };

  getStringsFromLocale = async (locale: string) => {
    if (this.supportedLanguages.includes(locale)) {
      //@ts-ignore
      return await localeBundles[locale].then((messages: any) => messages);
    } else {
      // default to DEFAULT_LOCALE
      //@ts-ignore
      return await localeBundles[DEFAULT_LOCALE].then(
        (messages: any) => messages
      );
    }
  };

  setStringsForLocale = (locale: string): void => {
    if (this.supportedLanguages.includes(locale)) {
      this.locale = locale;
      //@ts-ignore
      const status = fromPromise(localeBundles[locale]);
      const disposer = autorun(() => {
        if (status.state === FULFILLED) {
          //@ts-ignore
          this.strings = status.value;
          disposer();
        }
      });
    } else {
      // default to DEFAULT_LOCALE
      this.locale = DEFAULT_LOCALE;
      //@ts-ignore
      const status = fromPromise(localeBundles[DEFAULT_LOCALE]);
      const disposer = autorun(() => {
        if (status.state === FULFILLED) {
          //@ts-ignore
          this.strings = status.value;
          disposer();
        }
      });
    }
  };

  getSupportedLanguagesOptions = (): Array<OptionsType> => {
    return Object.keys(localeBundles).map((key) => ({
      value: key,
      label: key
    }));
  };
}

export const currentLocale = new Locale(DEFAULT_LOCALE);

export function getFirstBrowserLanguage() {
  const nav: any = window?.navigator;
  const browserLanguagePropertyKeys = [
    'language',
    'browserLanguage',
    'systemLanguage',
    'userLanguage'
  ];
  let i;
  let language;
  let len;
  let shortLanguage = null;

  // support for HTML 5.1 "navigator.languages"
  if (Array.isArray(nav.languages)) {
    for (i = 0; i < nav.languages.length; i++) {
      language = nav.languages[i];
      len = language.length;
      if (!shortLanguage && len) {
        shortLanguage = language;
      }
      if (language && len > 2) {
        return language;
      }
    }
  }

  // support for other well known properties in browsers
  for (i = 0; i < browserLanguagePropertyKeys.length; i++) {
    language = nav[browserLanguagePropertyKeys[i]];
    //skip this loop iteration if property is null/undefined.  IE11 fix.
    if (language == null) {
      continue;
    }
    len = language.length;
    if (!shortLanguage && len) {
      shortLanguage = language;
    }
    if (language && len > 2) {
      return language;
    }
  }

  return shortLanguage;
}

export function getSupportedLanguage() {
  // const lang = getFirstBrowserLanguage().toLowerCase();
  // if (SupportedLocales.includes(lang)) {
  //   return lang;
  // }
  return 'en-us';
}
