import { Injectable, Optional, SkipSelf } from '@angular/core';
import { ActivatedRouteSnapshot, Router } from '@angular/router';
import { noop } from 'rxjs';
import * as localization from 'devextreme/localization';
import * as deMessages from 'devextreme/localization/messages/de.json';
import * as enMessages from 'devextreme/localization/messages/en.json';
import * as frMessages from 'devextreme/localization/messages/fr.json';
import { getCurrencySymbol, getDateFormat, getDateTimeFormat, getDecimalSeparator, getLocaleCurrencyCode, getThousandSeparator } from '../../utils';
import { HenselTranslateService } from './hensel-translate.service';

const langMessages: { [key: string]: any } = { en: enMessages, de: deMessages, fr: frMessages };

type ShouldReuseRoute = (future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot) => boolean;

@Injectable({
  providedIn: 'root',
})


export class LocaleService {


  public dateFormat: string;
  public dateTimeFormat: string;
  public thousandSeparator: string;
  public decimalSeparator: string;
  public currencyCode: string;
  public currencySymbol: string;

  private initialized = false;

  private _currentCulture: string;
  get currentCulture(): string {
    return this._currentCulture;
  }
  set currentCulture(culture: string) {
    const oldCulture = this._currentCulture;
    this.setCultureWOReload(culture);
    if (oldCulture !== culture) setTimeout(() => this.reloadPages());
  }

  set currentLocale(culture: string) {
    this.setCultureWOReload(culture);
    this.currentLanguage = culture;
  }

  private _currentLanguage: string;
  get currentLanguage(): string {
    return this._currentLanguage;
  }
  set currentLanguage(lang: string) {
    this._currentLanguage = lang.split('-')[0]; //it can take culture as argument too
    // locale(this.currentLanguage);
    this.translate.use(lang);
  }

  constructor(
    private router: Router,
    public translate: HenselTranslateService,
    @Optional()
    @SkipSelf()
    otherInstance: LocaleService,
  ) {
    if (otherInstance) throw new Error('LocaleService should have only one instance.');
  }


  private setCultureWOReload(culture: string) {
    this._currentCulture = culture;
    this.dateFormat = getDateFormat(culture);
    this.dateTimeFormat = getDateTimeFormat(culture);
    this.thousandSeparator = getThousandSeparator(culture);
    this.decimalSeparator = getDecimalSeparator(culture);
    this.currencyCode = getLocaleCurrencyCode(culture);
    this.currencySymbol = getCurrencySymbol(culture);

    // const lang = culture.split('-')[0];
    // const messages = {};
    // messages[lang] = langMessages[this.currentLanguage];
    // localization.loadMessages(messages);
    localization.locale(culture);
  }

  private setRouteReuse(reuse: ShouldReuseRoute) {
    this.router.routeReuseStrategy.shouldReuseRoute = reuse;
  }

  private subscribeToLangChange() {
    this.translate.onLangChange.subscribe(() => {
      this.reloadPages();
    });
  }


  reloadPages = async () => {
    const { shouldReuseRoute } = this.router.routeReuseStrategy;

    this.setRouteReuse(() => false);
    this.router.navigated = false;

    await this.router.navigateByUrl(this.router.url).catch(noop);
    this.setRouteReuse(shouldReuseRoute);
  }


  initLocaleLanguage(culture: string, lang?: string) {
    if (this.initialized) return;

    this.setCultureWOReload(culture);
    this.currentLanguage = lang ?? culture;
    this.translate.setDefaultLang(this.currentLanguage);
    setTimeout(() => this.subscribeToLangChange(), 1000); //delay avoid to fire onLangChange at the init - app start, otherwise start url will be overwritten

    this.initialized = true;
    console.log('Locale is initialized !!');
  }


}
