class LisioDocumentLanguageController {
  private static _current: LisioDocumentLanguageController;

  private _hasSavedOriginalAttributes = false;
  private _originalDir: string | null = null;
  private _originalLang: string | null = null;
  private _originalXmlLang: string | null = null;
  private readonly _rtlLangs = ["ar", "yi", "he", "ps"];

  private constructor() {}

  public static get current() {
    if (!this._current) {
      this._current = new LisioDocumentLanguageController();
    }
    return this._current;
  }

  public get originalLang(): string {
    this.saveOriginalAttributes();
    return this.normalizeLangForAttribute(this._originalLang || "fr");
  }

  public applyTranslatedLanguage(lang: string, direction?: string): void {
    this.saveOriginalAttributes();
    if (lang === "default") {
      this.restoreOriginalLanguage();
      return;
    }
    const normalizedLang = this.normalizeLangForAttribute(lang);
    document.documentElement.lang = normalizedLang;
    document.documentElement.dir =
      direction || this.getDirectionForLanguage(normalizedLang);
  }

  public getDirectionForLanguage(lang: string): string {
    const primaryLang = this.normalizeLangForAttribute(lang).split("-")[0];
    return this._rtlLangs.includes(primaryLang) ? "rtl" : "ltr";
  }

  public normalizeLangForAttribute(lang: string): string {
    const parts = lang
      .replace(/_/g, "-")
      .split("-")
      .filter((part) => part.length > 0);

    return parts
      .map((part, index) =>
        index === 0 ? part.toLowerCase() : part.toUpperCase(),
      )
      .join("-");
  }

  public restoreOriginalLanguage(): void {
    this.saveOriginalAttributes();
    if (this._originalLang === null) {
      document.documentElement.removeAttribute("lang");
    } else {
      document.documentElement.lang = this._originalLang;
    }
    if (this._originalDir === null) {
      document.documentElement.removeAttribute("dir");
    } else {
      document.documentElement.dir = this._originalDir;
    }
    if (this._originalXmlLang === null) {
      document.documentElement.removeAttribute("xml:lang");
    } else {
      document.documentElement.setAttribute("xml:lang", this._originalXmlLang);
    }
  }

  private saveOriginalAttributes(): void {
    if (this._hasSavedOriginalAttributes) {
      return;
    }
    this._originalLang = document.documentElement.getAttribute("lang");
    this._originalDir = document.documentElement.getAttribute("dir");
    this._originalXmlLang = document.documentElement.getAttribute("xml:lang");
    this._hasSavedOriginalAttributes = true;
  }
}

export default LisioDocumentLanguageController;
