import styles from "../assets/css/shadowroot/modal/lisio-modal.css?raw";
import LisioShadowRootController from "./lisio-shadow-root-controller";
import { appendToHead } from "../utils";
import { LisioBlurController } from "./lisio-blur-controller";
import LisioTranslationController from "./lisio-translation-controller";

abstract class LisioModalController {
  private _metaViewport: HTMLMetaElement;
  private _oldViewportContent?: string;

  protected _isActive = false;
  protected _modalContainer: HTMLDivElement;

  protected _closeButton: HTMLButtonElement;
  protected _logo: HTMLImageElement;

  protected _modalBody: HTMLDivElement;

  protected _title?: HTMLParagraphElement;

  constructor(
    id: string,
    headerTitleId: string,
    headerTitleTextId: string,
    isTitleVisible: boolean,
  ) {
    // this._closeTextId = closeTextId;// widget
    this._modalContainer = document.createElement("div");
    this._modalContainer.id = id;
    this._modalContainer.classList.add("lisio-modal-container");
    this._modalContainer.setAttribute("aria-modal", "true");
    this._modalContainer.setAttribute("role", "dialog");
    this.keyDownHandler = this.keyDownHandler.bind(this);

    this._logo = document.createElement("img");
    this._logo.id = "lisio-modal-img";
    this._logo.alt = "";
    this._logo.setAttribute("aria-hidden", "true");
    this._logo.src = `${import.meta.env.VITE_LISIO_DOMAIN}/solution/dist-site/svg/hippo_logo.svg`;

    this._closeButton = document.createElement("button");
    this._closeButton?.classList.add("lisio-modal-close-button");
    this._closeButton.tabIndex = 0;
    this._closeButton.setAttribute(
      "aria-label",
      LisioTranslationController.current.getTranslation(
        "confirmation-modal-close",
      ),
    );
    this._closeButton.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="22" height="22" viewBox="0 0 22 22" fill="none"><path d="M1 1L20.9878 20.9783M21 1.0217L1.0122 21" stroke="currentColor" stroke-width="2" stroke-linecap="round"></path></svg>`;

    const header = document.createElement("div");
    header.classList.add("lisio-modal-header");
    header.appendChild(this._logo);
    header.appendChild(this._closeButton);

    this._modalBody = document.createElement("div");
    this._modalBody.classList.add("lisio-modal-body");

    this._modalContainer.appendChild(header);
    this._modalContainer.appendChild(this._modalBody);

    if (isTitleVisible) {
      this._modalContainer.setAttribute("aria-labelledby", headerTitleId);
      this._title = document.createElement("p");
      this._title.classList.add("lisio-modal-title");
      this._title.id = headerTitleId;
      this._title.innerText =
        LisioTranslationController.current.getTranslation(headerTitleTextId);
      this._modalBody.appendChild(this._title);
    } else {
      this._modalContainer.setAttribute(
        "aria-label",
        LisioTranslationController.current.getTranslation(headerTitleTextId),
      );
    }

    const viewportMeta = document.querySelector('meta[name="viewport"]') as
      | HTMLMetaElement
      | undefined;

    if (viewportMeta) {
      this._metaViewport = viewportMeta;
      this._oldViewportContent = viewportMeta.getAttribute("content") as
        | string
        | undefined;
      viewportMeta.setAttribute(
        "content",
        "height=device-height, width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no",
      );
    } else {
      const newViewportMeta = document.createElement("meta");
      this._metaViewport = newViewportMeta;
      newViewportMeta.setAttribute("name", "viewport");
      newViewportMeta.setAttribute(
        "content",
        "height=device-height, width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no",
      );
    }
    
    (this._modalContainer as HTMLElement)!.addEventListener("keydown", (e) => {
      if (e.code === "Escape") {
        this._closeButton?.click();
      }
    });
    window.addEventListener("lisio-lang-change", () => {
      LisioTranslationController.current.translateModal(
        this._closeButton,
        this._modalContainer,
        this._title,
        headerTitleTextId,
        isTitleVisible,
      );
    });
  }

  public closeModal() {
    //masquer
    LisioShadowRootController.current.removeElement(
      this._modalContainer,
      styles,
    );
    if (this._oldViewportContent != undefined) {
      this._metaViewport.content = this._oldViewportContent;
    } else {
      this._metaViewport.remove();
    }
    this._isActive = false;
    this._modalContainer.classList.remove("active");
    document.body.style.overflow = "auto";
    LisioBlurController.current.goOnBack();
  }

  public openModal() {
    LisioShadowRootController.current.appendElement(
      this._modalContainer,
      styles,
    );
    // à mettre dans le shadow root
    if (this._oldViewportContent == undefined) {
      appendToHead(this._metaViewport);
    }
    this._isActive = true;
    this._modalContainer.classList.add("active");
    document.body.style.overflow = "hidden";
    this.activateFocusTrap();
    if (!LisioBlurController.current.isActive) {
      LisioBlurController.current.enableBlur();
      LisioBlurController.current.goOnTop();
    }
  }

  public setDataFocus(element: HTMLElement, parameterName: string) {
    element.dataset.focus = parameterName;
  }

  private getFocusableElements() {
    return (
      Array.from(this._modalContainer.querySelectorAll("*")) as HTMLElement[]
    ).filter((el) => {
      const e = el as
        | HTMLButtonElement
        | HTMLInputElement
        | HTMLSelectElement
        | HTMLTextAreaElement;
      return el.tabIndex >= 0 && !e.disabled && el.offsetParent !== null;
    });
  }

  private keyDownHandler = (e: KeyboardEvent) => {
    if (e.code !== "Tab") return;

    const focusables = this.getFocusableElements();
    if (focusables.length === 0) return;

    const firstEl = focusables[0];
    const lastEl = focusables[focusables.length - 1];

    const focusedEl = this._modalContainer.querySelector(":focus");

    if (e.shiftKey) {
      if (
        focusedEl === firstEl ||
        focusedEl === this._modalContainer ||
        focusedEl === null
      ) {
        e.preventDefault();
        lastEl.focus();
      }
    } else {
      if (focusedEl === lastEl || focusedEl === null) {
        e.preventDefault();
        firstEl.focus();
      }
    }
  };

  private clickHandler = (e: MouseEvent) => {
    if (e.isTrusted) {
      const focusables = this.getFocusableElements();
      focusables[0].focus();
    }
  };

  private activateFocusTrap() {
    document.addEventListener("keydown", this.keyDownHandler);
    document.addEventListener("click", this.clickHandler);
    const focusables = this.getFocusableElements();
    focusables[0].focus();
  }

  public deactivateFocusTrap() {
    document.removeEventListener("keydown", this.keyDownHandler);
    document.removeEventListener("click", this.clickHandler);
  }
}

export default LisioModalController;
