import styles from "../assets/css/shadowroot/lisio-bubble.css?raw";
import LisioShadowRootController from "../controllers/lisio-shadow-root-controller";
import LisioTextTreeWalker from "../walkers/lisio-text-tree-walker";
import LisioAdapter from "./lisio-adapter";

/**
 * Class representing a show alt adapter extending an adapter.\
 * It aims to represents the font style functionality of Lisio.\
 * A show alt adapter is basically a functionality of Lisio which will change the show alt of texts in the main page.\
 */
class LisioShowAltAdapter extends LisioAdapter<boolean> {
  private _bubble: HTMLDivElement | undefined;
  private _mouseEnterHandlerBind = this.mouseEnterHandler.bind(this);
  private _mouseMoveHandlerBind = this.mouseMoveHandler.bind(this);
  private _mouseOutHandlerBind = this.mouseOutHandler.bind(this);

  /**
   * Public method implementing abstract method adapt of Adapter
   * @param {LisioTextTreeWalker} walker - A walker to explore the DOM
   * @param {boolean} value - Value of the functionality
   * @returns Returns nothing
   * @source
   */
  public adapt(_: LisioTextTreeWalker, value: boolean): void {
    const imgs = document.body.querySelectorAll("img"); //on récupère les images
    for (const img of imgs) {
      this.adaptFunction(img, value);
    }

    if (value && this._bubble == undefined) {
      this._bubble = document.createElement("div");
      this._bubble.id = "lisio-bubble";
      this._bubble.classList.add("lisio-bubble", "lisio-hidden");
      LisioShadowRootController.current.appendElement(this._bubble, styles);
    } else if (this._bubble != undefined) {
      LisioShadowRootController.current.removeElement(this._bubble, styles);
      this._bubble = undefined;
    }
  }

  protected adaptFunction(element: HTMLElement, value: boolean): void {
    if (value && !(element as HTMLImageElement).src.includes("/solution")) {
      //si activé
      element.addEventListener("mouseenter", this._mouseEnterHandlerBind);
      element.addEventListener("mousemove", this._mouseMoveHandlerBind);
      element.addEventListener("mouseout", this._mouseOutHandlerBind);
    } else if (
      !value &&
      !(element as HTMLImageElement).src.includes("/solution")
    ) {
      element.removeEventListener("mouseenter", this._mouseEnterHandlerBind);
      element.removeEventListener("mousemove", this._mouseMoveHandlerBind);
      element.removeEventListener("mouseout", this._mouseOutHandlerBind);
    }
  }

  private mouseEnterHandler(event: MouseEvent) {
    if (this._bubble != undefined) {
      if (this._bubble.textContent === "") {
        const txt = (event.target as HTMLImageElement).alt;
        if (txt != null && txt.trim() != "") {
          this._bubble.textContent = txt;
        } else {
          this._bubble.textContent = "Pas de description";
        }
      }
      this._bubble.classList.remove("lisio-hidden");
    }
  }

  private mouseMoveHandler(event: MouseEvent) {
    if (this._bubble != undefined) {
      this._bubble.style.top = `${event.clientY - 15}px`;
      this._bubble.style.left = `${event.clientX + 15}px`;
    }
  }

  private mouseOutHandler() {
    if (this._bubble != undefined) {
      this._bubble.textContent = ""; //on vide le texte
      this._bubble.classList.add("lisio-hidden");
    }
  }
}

export default LisioShowAltAdapter;
