import {
  LisioBooleanParameterNames,
  LisioCategoryNames,
  LisioNumericParameterNames,
  LisioParameterNames,
  LisioProfileNames,
  LisioStringParameterNames,
} from "@lisio/lisio-profils";

import { lisioConfig } from "./lisio-config";

interface TabsToHide {
  categoriesToHide: LisioCategoryNames[];
  compensation: boolean;
  parametersToHide: LisioParameterNames[];
  profilesToHide: LisioProfileNames[];
  translationMode: "deepl_translation" | "google_translation" | "none";
}

/**
 * Convertie les données reçu dans tabsToHide pour correspondre aux valeurs et format attendus par le back
 */
function convertTabstoHide(tabsToHide: string[]): TabsToHide {
  const newTabsToHide: TabsToHide = {
    categoriesToHide: [],
    profilesToHide: [],
    parametersToHide: [],
    translationMode: "google_translation",
    compensation: true,
  };

  if (tabsToHide.includes("compensation")) {
    newTabsToHide.compensation = false;
  }
  if (tabsToHide.includes("trad")) {
    newTabsToHide.translationMode = "none";
  } else if (tabsToHide.includes("tradGoogle")) {
    newTabsToHide.translationMode = "deepl_translation";
  }

  if (tabsToHide.includes("eco")) {
    tabsToHide.push("ecological");
    tabsToHide.push("light_ecological");
  }

  if (tabsToHide.includes("zoom")) {
    tabsToHide.push("glass_x2");
    tabsToHide.push("glass_x4");
    tabsToHide.push("zoom");
  }

  if (!("speechSynthesis" in window)) {
    tabsToHide.push("speech_synthesis");
  }

  const categoryNames: LisioCategoryNames[] = Object.values(LisioCategoryNames);
  const profileNames: LisioProfileNames[] = Object.values(LisioProfileNames);
  const parameterNames: LisioParameterNames[] = [
    ...Object.values(LisioBooleanParameterNames),
    ...Object.values(LisioNumericParameterNames),
    ...Object.values(LisioStringParameterNames),
  ];

  tabsToHide.forEach((element) => {
    if (categoryNames.includes(element as LisioCategoryNames)) {
      newTabsToHide.categoriesToHide.push(element as LisioCategoryNames);
    } else if (profileNames.includes(element as LisioProfileNames)) {
      newTabsToHide.profilesToHide.push(element as LisioProfileNames);
    } else if (parameterNames.includes(element as LisioParameterNames)) {
      newTabsToHide.parametersToHide.push(element as LisioParameterNames);
    }
  });
  return newTabsToHide;
}

function decodeHTMLEntity(entity: string) {
  const textarea = document.createElement("textarea");
  textarea.innerHTML = entity;
  return textarea.value;
}

function domainFromUrl(url: string) {
  let result, match;
  if (
    (match = url.match(
      // eslint-disable-next-line no-useless-escape
      /^(?:https?:\/\/)?(?:[^@\n]+@)?(?:www\.)?([^:\/\n\?\=]+)/im,
    ))
  ) {
    result = match[0];
  }
  return result;
}

function escapeRegexSpecialChars(word: string) {
  return word.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}

function isInViewport(element: HTMLElement) {
  const box = element.getBoundingClientRect();

  const body = document.body;
  const docEl = document.documentElement;

  const scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop;
  const scrollLeft = window.pageXOffset || docEl.scrollLeft || body.scrollLeft;

  const clientTop = docEl.clientTop || body.clientTop || 0;
  const clientLeft = docEl.clientLeft || body.clientLeft || 0;

  const top = box.top + scrollTop - clientTop;
  const left = box.left + scrollLeft - clientLeft;
  const bottom = box.bottom - scrollTop - clientTop;
  const right = box.right - scrollLeft - clientLeft;

  const styles = window.getComputedStyle(element);
  return (
    top >= 0 &&
    left >= 0 &&
    bottom <= document.documentElement.scrollHeight &&
    right <= document.documentElement.scrollWidth &&
    styles.display != "none" &&
    styles.visibility != "hidden"
    //element.getClientRects().length != 0
  );
}

function isTouchDeviceLisio() {
  try {
    document.createEvent("TouchEvent");
    return true;
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
  } catch (error) {
    return false;
  }
}

function kebabToCamel(str: string) {
  return str.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
}

function lisioGetInitLang() {
  const detectedLang = document.documentElement.lang
    .toLowerCase()
    .replace("-", "_");

  const googleLangs = [
    "ar",
    "bg",
    "br",
    "ca",
    "co",
    "cs",
    "cy",
    "da",
    "de",
    "el",
    "en",
    "es",
    "et",
    "eu",
    "fi",
    "fr",
    "he",
    "hi",
    "hu",
    "it",
    "ja",
    "ko",
    "lb",
    "lt",
    "lv",
    "nl",
    "no",
    "oc",
    "pl",
    "ps",
    "pt",
    "ro",
    "ru",
    "sk",
    "sl",
    "sv",
    "th",
    "tr",
    "uk",
    "vi",
    "yi",
    "zh",
    "zh_cn",
  ];
  const deeplLangs = [
    "ar",
    "bg",
    "cs",
    "da",
    "de",
    "el",
    "en",
    "en_gb",
    "en_us",
    "es",
    "et",
    "fi",
    "fr",
    "hu",
    "id",
    "it",
    "ja",
    "ko",
    "lt",
    "lv",
    "nb",
    "nl",
    "pl",
    "pt",
    "pt_br",
    "pt_pt",
    "ro",
    "ru",
    "sk",
    "sl",
    "sv",
    "tr",
    "uk",
    "zh",
  ];

  const supportedLangs = lisioConfig.userSettings.tabsToHide.includes(
    "tradGoogle",
  )
    ? deeplLangs
    : googleLangs;

  if (supportedLangs.includes(detectedLang)) {
    return detectedLang;
  }

  const baseLang = detectedLang.includes("_")
    ? detectedLang.split("_")[0]
    : detectedLang;
  return supportedLangs.includes(baseLang) ? baseLang : "fr";
}

function appendToHead(element: HTMLElement) {
  if (document.head.append.toString().includes("[native code]")) {
    document.head.append(element);
  } else {
    document.head.appendChild(element);
  }
}

function setAttributeRecursive(elementToSet: HTMLElement, attributes: object) {
  for (const [name, value] of Object.entries(attributes)) {
    const normalizedName = name.replace(/_/g, "-");
    if (typeof value === "object") {
      elementToSet.setAttribute(
        normalizedName,
        Object.entries(value)
          .map(([name, value]) => `${name}:${value}`)
          .join(";"),
      );
    } else {
      elementToSet.setAttribute(normalizedName, value.toString());
    }
  }
}

export {
  domainFromUrl,
  convertTabstoHide,
  isInViewport,
  isTouchDeviceLisio,
  escapeRegexSpecialChars,
  decodeHTMLEntity,
  lisioGetInitLang,
  kebabToCamel,
  setAttributeRecursive,
  appendToHead,
};

export type { TabsToHide };
