import { i18n } from '@plugins/i18n';
import {
  mapState,
  mapGetters,
  mapActions,
  GetterTree,
  MutationTree,
  ActionTree,
  ActionMethod,
  Mapper,
  ActionContext,
} from 'vuex';
import { Quasar } from 'quasar';
import { langDictionary } from '@/quasar';
import { DateFormat } from '@constants/utils/format-date';

interface State {
  locale: string;
  locales: {
    [key: string]: string;
  };
  localeMasks: {
    en: {
      input: string;
      date: DateFormat.usDate;
    };
    ru: {
      input: string;
      inputDatetime: string;
      date: DateFormat.date;
      datetime: DateFormat.datetime;
    };
  };
}

export const state: State = {
  locale: 'ru',
  locales: {
    en: 'English',
    ru: 'Русский',
  },
  localeMasks: {
    en: {
      input: '##/##/####',
      date: DateFormat.usDate,
    },
    ru: {
      input: '##.##.####',
      inputDatetime: '##.##.#### ##:##',
      date: DateFormat.date,
      datetime: DateFormat.datetime,
    },
  },
};

function getLocaleComparator(locale: string) {
  // @ts-ignore
  if (getLocaleComparator.cache[locale]) {
    // @ts-ignore
    return getLocaleComparator.cache[locale];
  }
  try {
    return new Intl.Collator([locale], { numeric: true }).compare;
  } catch (e) {
    return (a: number, b: number) => (a > b ? 1 : a < b ? -1 : 0);
  }
}

getLocaleComparator.cache = {};

export const getters: GetterTree<State, State> = {
  locale(state) {
    return state.locale;
  },
  locales(state) {
    return state.locales;
  },
  localeMask(state) {
    // @ts-ignore
    return state.localeMasks[state.locale] || state.localeMasks.en;
  },
  localeComparator() {
    return getLocaleComparator(state.locale);
  },
};

export const mutations: MutationTree<State> = {
  locale(state, locale) {
    state.locale = locale;
  },
  locales(state, locales) {
    state.locale = locales;
  },
};

export const actions: ActionTree<State, State> = {
  dispatchLocale(
    { commit, getters }: ActionContext<State, State>,
    { locale }: Record<string, string>
  ) {
    commit('locale', locale);

    i18n.locale = getters.locale;

    // @ts-ignore
    Quasar.lang.set(langDictionary[locale]);
  },
  dispatchLocales(
    { commit }: ActionContext<State, State>,
    { locales }: Record<string, string>
  ) {
    commit('locales', locales);
  },
};

export const i18nComputed = {
  ...mapState<Mapper<State>>('i18N', {
    locale: (state: State) => state.locale,
    locales: (state: State) => state.locales,
  }),
  ...mapGetters('i18N', ['locale', 'locales']),
};

export const i18nMethods: {
  dispatchLocale: ActionMethod;
  dispatchLocales: ActionMethod;
} = mapActions('i18N', ['dispatchLocale', 'dispatchLocales']);
