import { defautValueOfNumericParameters, LisioNumericParameterNames } from "@lisio/lisio-profils";
import LisioStyleSheetController from "../../controllers/lisio-stylesheet-controller";
import LisioCSSProperties from "../../enums/lisio-css-properties";
import { kebabToCamel } from "../../utils";
import LisioAdapter from "../lisio-adapter";

abstract class LisioFontStyleAdapter extends LisioAdapter<number> {
  protected _extraProperties: Map<string, string> = new Map<string, string>([
    [LisioCSSProperties.OVERFLOW_WRAP, "break-word"],
    [LisioCSSProperties.WORD_BREAK, "break-word"],
    [LisioCSSProperties.HYPHENS, "auto"],
  ]);
  protected _fontStyle:
    | LisioCSSProperties.FONT_SIZE
    | LisioCSSProperties.LETTER_SPACING
    | LisioCSSProperties.LINE_HEIGHT
    | LisioCSSProperties.WORD_SPACING;

  /**
   * Constructor of class {@link Adapter | Adapter}
   * @param {LisioCSSProperties.FONT_SIZE | LisioCSSProperties.LETTER_SPACING | LisioCSSProperties.LINE_HEIGHT | LisioCSSProperties.WORD_SPACING} fontStyle - Name of font style to modify
   */
  constructor(
    fontStyle:
      | LisioCSSProperties.FONT_SIZE
      | LisioCSSProperties.LETTER_SPACING
      | LisioCSSProperties.LINE_HEIGHT
      | LisioCSSProperties.WORD_SPACING,
  ) {
    super();
    this._fontStyle = fontStyle;
  }

  protected fontStyleCalculator(adapter: LisioNumericParameterNames.FONT_SIZE | LisioNumericParameterNames.LINE_HEIGHT | LisioNumericParameterNames.LETTER_SPACING | LisioNumericParameterNames.WORD_SPACING, element: HTMLElement, value: number): number {
    if(defautValueOfNumericParameters.get(adapter) === value){
      // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
      delete element.dataset[kebabToCamel(`lisio-${this._fontStyle}`)];
      if (this._fontStyle == "font-size") {
        delete element.dataset.lisioLineHeight;
      }
      return -1;
    }else{
      let currentValue: string | undefined =
        element.dataset[kebabToCamel(`lisio-${this._fontStyle}`)];
      const stylesToSave: Map<LisioCSSProperties, string> = new Map<
        LisioCSSProperties,
        string
      >();
      let currentNumericValue;
      if (currentValue == null) {
        const computedStyle = window.getComputedStyle(element);
        currentValue = computedStyle.getPropertyValue(this._fontStyle); // on récupère la valeur du style de base si elle n'a jamais été récupéré
        if (currentValue == "normal") {
          // ajustemment pour la valeur "normale"
          if (this._fontStyle == "line-height") {
            currentNumericValue =
              Number.parseFloat(computedStyle.getPropertyValue("font-size")) *
              1.2;
          } else if (this._fontStyle == "letter-spacing") {
            currentNumericValue = 2;
          } else if (this._fontStyle == "word-spacing") {
            currentNumericValue =
              Number.parseFloat(computedStyle.getPropertyValue("font-size")) *
              1.25;
          }
        } else {
          currentNumericValue = Number.parseFloat(currentValue);
          if (currentNumericValue === 0 && this._fontStyle == "word-spacing") {
            currentNumericValue = 1;
          }
        }
        if (currentNumericValue != undefined) {
          stylesToSave.set(this._fontStyle, currentNumericValue.toString());
        }
      } else {
        currentNumericValue = Number.parseFloat(currentValue);
      }
  
      let adpatedValue = -1;
      if (currentNumericValue != undefined) {
        if (this._fontStyle == "font-size") {
          if (currentNumericValue < 14) {
            adpatedValue = Math.ceil(currentNumericValue + 5 * value);
          } else if (currentNumericValue < 20) {
            adpatedValue = Math.ceil(currentNumericValue + 3.5 * value);
          } else {
            adpatedValue = Math.ceil(currentNumericValue + 3 * value);
          }
          stylesToSave.set(
            LisioCSSProperties.LINE_HEIGHT,
            Math.ceil(adpatedValue * 1.2).toString(),
          );
        } else {
          adpatedValue = Math.ceil(currentNumericValue * value);
        }
      }
      if (
        element.dataset[kebabToCamel(`lisio-${this._fontStyle}`)] == undefined
      ) {
        this.saveInAttributes(element, stylesToSave);
      }
      return adpatedValue;
    }
  }

  protected fontStyleCalculatorApply(
    elementToCheck: HTMLElement,
    value: number,
  ) {
    LisioStyleSheetController.current.replaceImportantInStyleAttribute(
      [this._fontStyle],
      elementToCheck,
    );
    const oldSelector = this.findOldSelector(elementToCheck, this._fontStyle);
    if (oldSelector != "") {
      elementToCheck.classList.remove(oldSelector);
    }
    if(value === -1){
      LisioStyleSheetController.current.removeRule(oldSelector);
      if (this._fontStyle === LisioCSSProperties.LINE_HEIGHT) {
        elementToCheck.classList.remove("lisio-lh-priority");
      }
    }else{
      const newSelector = `lisio-${this._fontStyle}-${value}`;
      elementToCheck.classList.add(newSelector);
      if (this._fontStyle === LisioCSSProperties.LINE_HEIGHT) {
        elementToCheck.classList.add("lisio-lh-priority");
      }
      this._extraProperties.set(this._fontStyle, `${value.toString()}px`);
      LisioStyleSheetController.current.insertOrReplaceRule(
        this._extraProperties,
        `.${newSelector}${
          this._fontStyle === LisioCSSProperties.LINE_HEIGHT
            ? ".lisio-lh-priority"
            : ""
        }`,
        `.${oldSelector}`,
      );
    }
  }
}

export default LisioFontStyleAdapter;
