import { ThemeOptions } from "@lisio/lisio-profils";

import LisioStyleSheetController from "../controllers/lisio-stylesheet-controller";
import LisioCSSProperties from "../enums/lisio-css-properties";
import LisioTextTreeWalker from "../walkers/lisio-text-tree-walker";
import LisioAdapter from "./lisio-adapter";

/**
 * Class representing a theme adapter extending an adapter.\
 * It aims to represents the font style functionality of Lisio.\
 * A theme adapter is basically a functionality of Lisio which will change the theme of texts in the main page.\
 */
class LisioThemeAdapter extends LisioAdapter<string> {
  /**
   * Public method implementing abstract method adapt of Adapter
   * @param {LisioTextTreeWalker} walker - A walker to explore the DOM
   * @param {string} value - Value of the functionality
   * @returns Returns nothing
   * @source
   */
  public adapt(_walker: LisioTextTreeWalker, value: string): void {
    for (const tag of document.body.querySelectorAll<HTMLElement>(
      "*:not(script):not(link):not(style):not(svg)",
    )) {
      if (tag.localName != "option") {
        this.adaptFunction(tag, value);
      }
    }
    document.body.classList.add(`lisio-theme`); //on l'ajoute au this.body si elle n'est pas présente

    const propertiesToAdd = new Map<LisioCSSProperties, string>([
      [LisioCSSProperties.BACKGROUND, "none"],
      [LisioCSSProperties.BACKGROUND_IMAGE, "none"],
    ]);
    if (value === ThemeOptions.C_Y_BG_BL) {
      //attribution des valeurs
      propertiesToAdd.set(LisioCSSProperties.COLOR, "yellow");
      propertiesToAdd.set(LisioCSSProperties.BORDER_COLOR, "yellow");
      propertiesToAdd.set(LisioCSSProperties.BACKGROUND_COLOR, "blue");
    } else if (value == ThemeOptions.C_BL_BG_W) {
      propertiesToAdd.set(LisioCSSProperties.COLOR, "blue");
      propertiesToAdd.set(LisioCSSProperties.BORDER_COLOR, "blue");
      propertiesToAdd.set(LisioCSSProperties.BACKGROUND_COLOR, "white");
    } else if (value == ThemeOptions.C_W_BG_BK) {
      propertiesToAdd.set(LisioCSSProperties.COLOR, "white");
      propertiesToAdd.set(LisioCSSProperties.BORDER_COLOR, "white");
      propertiesToAdd.set(LisioCSSProperties.BACKGROUND_COLOR, "black");
    } else if (value == ThemeOptions.C_BK_BG_W) {
      propertiesToAdd.set(LisioCSSProperties.COLOR, "black");
      propertiesToAdd.set(LisioCSSProperties.BORDER_COLOR, "black");
      propertiesToAdd.set(LisioCSSProperties.BACKGROUND_COLOR, "white");
    } else if (value == ThemeOptions.C_BK_BG_G) {
      propertiesToAdd.set(LisioCSSProperties.COLOR, "black");
      propertiesToAdd.set(LisioCSSProperties.BORDER_COLOR, "black");
      propertiesToAdd.set(LisioCSSProperties.BACKGROUND_COLOR, "#E8E8E8");
    } else if (value == ThemeOptions.C_W_BG_GY) {
      propertiesToAdd.set(LisioCSSProperties.COLOR, "#DFE3E7");
      propertiesToAdd.set(LisioCSSProperties.BORDER_COLOR, "#DFE3E7");
      propertiesToAdd.set(LisioCSSProperties.BACKGROUND_COLOR, "#212629");
    }
    if (value === "default") {
      LisioStyleSheetController.current.removeRule(".lisio-theme");
      LisioStyleSheetController.current.removeRule(".lisio-theme-form");
      LisioStyleSheetController.current.removeRule(
        ".lisio-theme-form::placeholder",
      );
      LisioStyleSheetController.current.removeRule(".lisio-theme-image");
    } else {
      LisioStyleSheetController.current.insertOrReplaceRule(
        propertiesToAdd,
        ".lisio-theme",
        ".lisio-theme",
      );
      LisioStyleSheetController.current.insertOrReplaceRule(
        propertiesToAdd,
        ".lisio-theme-form",
        ".lisio-theme-form",
      );
      LisioStyleSheetController.current.insertOrReplaceRule(
        propertiesToAdd,
        ".lisio-theme-form::placeholder",
        ".lisio-theme-form::placeholder",
      );
      LisioStyleSheetController.current.insertRule(
        ".lisio-theme-image",
        new Map<LisioCSSProperties, string>([
          [LisioCSSProperties.FILTER, "brightness(50%)"],
        ]),
      );
      // propertiesToAdd.delete(LisioCSSProperties.BORDER_COLOR);
      propertiesToAdd.set(
        LisioCSSProperties._WEBKIT_TEXT_FILL_COLOR,
        "initial",
      );
      LisioStyleSheetController.current.insertOrReplaceRule(
        propertiesToAdd,
        ".lisio-theme-text",
        ".lisio-theme-text",
      );
    }

    // exec = /html \*\.lisio-theme-text{(.*?)}/g.exec(this.styleSheet.innerText); //on regarde si elle est présente ou non dans le style
    // if (exec != null) {
    //     this.styleSheet.innerText = this.styleSheet.innerText.replace(exec[0], `html *.lisio-theme-text{ color:${color}!important; background-color:${bg}!important; -webkit-text-fill-color: initial!important}`);
    // } else { //si non on ajoute
    //     this.styleSheet.innerText += `html *.lisio-theme-text{ color:${color}!important; background-color:${bg}!important; -webkit-text-fill-color: initial!important;}`;
    // }
  }

  protected adaptFunction(element: HTMLElement, value: string): void {
    if (value == "default") {
      //si value par default
      if (element.classList.contains("lisio-theme")) {
        element.classList.remove("lisio-theme");
      } else if (element.classList.contains("lisio-theme-form")) {
        element.classList.remove("lisio-theme-form");
      } else if (element.classList.contains("lisio-theme-image")) {
        element.classList.remove("lisio-theme-image");
      } else if (element.classList.contains("lisio-theme-text")) {
        element.classList.remove("lisio-theme-text");
      }
      if (
        element.localName != "style" &&
        element.localName != "svg" &&
        element.localName != "filter" &&
        element.localName != "feColorMatrix" &&
        !element.classList.contains("blur_lisio")
      ) {
        //on enlève quelques balises
        element.classList.remove("lisio-theme"); // on supprime la classe
        element.classList.remove("lisio-theme-form");
        element.classList.remove("lisio-theme-image");
      }
    } else {
      document.body.classList.remove("lisio-theme");
      // this.walkTxt.currentNode = this.walkTxt.root; //on initialise
      // while (n = this.walkTxt.nextNode()) {
      //     if (element.nodeValue.trim() != "" && element.parentElement.tagName != "SCRIPT" && element.parentElement.tagName != "STYLE") {
      //         element.parentElement.classList.remove("lisio-theme-text");
      //     }
      const styles = window.getComputedStyle(element);
      if (
        element.textContent != undefined &&
        element.textContent.trim() != ""
      ) {
        element.classList.add("lisio-theme-text");
      } else if (
        !/rgba\(\s?0\s?,\s?0\s?,\s?0\s?,\s?0\s?\)/.test(styles.background) &&
        !/rgb\(\s?0\s?,\s?0\s?,\s?0\s?\)/.test(styles.background) &&
        styles.background != "none" &&
        !element.classList.contains("blur_lisio")
      ) {
        if (
          styles.backgroundImage != "none" &&
          value == ThemeOptions.C_W_BG_BK
        ) {
          element.classList.add("lisio-theme-image");
        } else {
          if (
            element.localName === "input" ||
            element.localName === "select" ||
            element.localName === "textarea" ||
            element.localName === "optgroup" ||
            element.localName === "option"
          ) {
            //on regarde si c'est du formulaire
            element.classList.add(`lisio-theme-form`); //on ajoute la classe
          } else if (
            (/lisio-theme-\w+/g.exec(element.className) == null ||
              element.className == "") &&
            element.localName !== "br"
          ) {
            //sinon on ajoute la classe si elle n'existe pas déjà
            element.classList.add(`lisio-theme`);
          }
        }
        LisioStyleSheetController.current.replaceImportantInStyleAttribute(
          [
            LisioCSSProperties.BACKGROUND_COLOR,
            LisioCSSProperties.COLOR,
            LisioCSSProperties.BORDER_COLOR,
            LisioCSSProperties.BACKGROUND,
            LisioCSSProperties.BACKGROUND_IMAGE,
          ],
          element,
        );
      }
      // this.walkTxt.currentNode = this.walkTxt.root; //on initialise
      // while (n = this.walkTxt.nextNode()) {
      //     if (element.nodeValue.trim() != "" && element.parentElement.tagName != "SCRIPT" && element.parentElement.tagName != "STYLE") {
      //         element.parentElement.classList.add("lisio-theme-text");
      //     }
      // }
    }
  }
}

export default LisioThemeAdapter;
