document.addEventListener("DOMContentLoaded", function () {
  //
  const colorsManagerContainer = document.getElementById("ctmd-colors-manager");

  // --- Color Picker Initialization ---
  function initializeColorPicker(wrapper) {
    if (
      colorsManagerContainer &&
      colorsManagerContainer.classList.contains("ctmd-is-locked")
    ) {
      return; // Do not initialize pickers if the UI is locked
    }
    const displayInput = wrapper.querySelector(".ctmd-color-input-display");
    const dataInput = wrapper.querySelector(".ctmd-color-input");
    const swatch = wrapper.querySelector(".ctmd-color-swatch");

    if (!displayInput || !swatch || swatch.picker) {
      return;
    }

    const picker = new Picker({
      parent: swatch,
      color: displayInput.value,
      alpha: true,
      editor: true,
      editorFormat: "hex",
      popup: true,
      onDone: function (color) {
        const hasAlpha = color.hsla[3] < 1;
        let finalColor;

        if (hasAlpha) {
          const [r, g, b, a] = color.rgba;
          finalColor = `rgba(${r}, ${g}, ${b}, ${a.toFixed(2)})`;
        } else {
          finalColor = color.hex.substring(0, 7);
        }

        swatch.style.backgroundColor = color.rgbaString;
        displayInput.value = finalColor;
        dataInput.value = finalColor;

        const row = wrapper.closest("tr");
        if (row) {
          const rgbaObj = {
            r: color.rgba[0],
            g: color.rgba[1],
            b: color.rgba[2],
            a: color.rgba[3],
          };
          updateRowDisplayValues(row, rgbaObj);
        }
        dataInput.dispatchEvent(new Event("change", { bubbles: true }));
        updateAllDerivativeDisplays();
      },
    });
    swatch.picker = picker;
  }

  // --- Derivative Color Modal Logic ---
  const colorResolver = {
    parseColor: function (str) {
      if (typeof str !== "string") return { r: 0, g: 0, b: 0, a: 1 };
      str = str.trim().toLowerCase();
      if (str.startsWith("#")) {
        let hex = str.substring(1);
        if (hex.length === 3 || hex.length === 4)
          hex = hex
            .split("")
            .map((c) => c + c)
            .join("");
        if (hex.length === 6)
          return {
            r: parseInt(hex.substring(0, 2), 16),
            g: parseInt(hex.substring(2, 4), 16),
            b: parseInt(hex.substring(4, 6), 16),
            a: 1,
          };
        if (hex.length === 8)
          return {
            r: parseInt(hex.substring(0, 2), 16),
            g: parseInt(hex.substring(2, 4), 16),
            b: parseInt(hex.substring(4, 6), 16),
            a: parseInt(hex.substring(6, 8), 16) / 255,
          };
      }
      const parts = str.match(/[\d.]+/g);
      if (!parts) return { r: 0, g: 0, b: 0, a: 1 };
      if (str.startsWith("rgba"))
        return { r: +parts[0], g: +parts[1], b: +parts[2], a: +parts[3] };
      if (str.startsWith("rgb"))
        return { r: +parts[0], g: +parts[1], b: +parts[2], a: 1 };
      if (str.startsWith("hsla")) {
        const rgb = this.hslToRgb(+parts[0], +parts[1], +parts[2]);
        return { ...rgb, a: +parts[3] };
      }
      if (str.startsWith("hsl"))
        return { ...this.hslToRgb(+parts[0], +parts[1], +parts[2]), a: 1 };
      return { r: 0, g: 0, b: 0, a: 1 };
    },
    rgbToHsl: function (r, g, b) {
      r /= 255;
      g /= 255;
      b /= 255;
      const max = Math.max(r, g, b),
        min = Math.min(r, g, b);
      let h,
        s,
        l = (max + min) / 2;
      if (max === min) {
        h = s = 0;
      } else {
        const d = max - min;
        s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
        switch (max) {
          case r:
            h = (g - b) / d + (g < b ? 6 : 0);
            break;
          case g:
            h = (b - r) / d + 2;
            break;
          case b:
            h = (r - g) / d + 4;
            break;
        }
        h /= 6;
      }
      return { h: h * 360, s: s * 100, l: l * 100 };
    },
    hslToRgb: function (h, s, l) {
      s /= 100;
      l /= 100;
      let r, g, b;
      if (s === 0) {
        r = g = b = l;
      } else {
        const hue2rgb = (p, q, t) => {
          if (t < 0) t += 1;
          if (t > 1) t -= 1;
          if (t < 1 / 6) return p + (q - p) * 6 * t;
          if (t < 1 / 2) return q;
          if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
          return p;
        };
        const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
        const p = 2 * l - q;
        r = hue2rgb(p, q, h / 360 + 1 / 3);
        g = hue2rgb(p, q, h / 360);
        b = hue2rgb(p, q, h / 360 - 1 / 3);
      }
      return {
        r: Math.round(r * 255),
        g: Math.round(g * 255),
        b: Math.round(b * 255),
      };
    },
    applySettings: function (rgba, settings) {
      let { h, s, l } = this.rgbToHsl(rgba.r, rgba.g, rgba.b);
      let a = rgba.a;
      if (settings.hue) h = (h + settings.hue) % 360;
      if (h < 0) h += 360;
      if (settings.saturation)
        s = Math.max(0, Math.min(100, s + settings.saturation));
      if (settings.lightness)
        l = Math.max(0, Math.min(100, l + settings.lightness));
      if (settings.opacity !== undefined)
        a = Math.max(0, Math.min(100, settings.opacity)) / 100;
      const newRgb = this.hslToRgb(h, s, l);
      return { ...newRgb, a: a };
    },
    resolveColor: function (colorString, allColorsMap, maxDepth = 10) {
      if (!colorString.startsWith("$variable") || maxDepth <= 0) {
        return this.parseColor(colorString);
      }
      try {
        const jsonStr = colorString.substring(10, colorString.length - 2);
        const data = JSON.parse(jsonStr);
        const parentId = data.value.name;
        const settings = data.value.settings || {};
        if (!allColorsMap[parentId]) return { r: 0, g: 0, b: 0, a: 1 };
        const parentRgba = this.resolveColor(
          allColorsMap[parentId].rawValue,
          allColorsMap,
          maxDepth - 1
        );
        return this.applySettings(parentRgba, settings);
      } catch (e) {
        return { r: 0, g: 0, b: 0, a: 1 };
      }
    },
  };

  const derivativeModal = document.getElementById("ctmd-derivative-modal");

  if (derivativeModal) {
    const modalBackdrop = document.getElementById("ctmd-modal-backdrop");
    const parentColorSelect = document.getElementById("ctmd-parent-color");
    const hueSlider = document.getElementById("ctmd-hue-slider");
    const hueValue = document.getElementById("ctmd-hue-value");
    const saturationSlider = document.getElementById("ctmd-saturation-slider");
    const saturationValue = document.getElementById("ctmd-saturation-value");
    const lightnessSlider = document.getElementById("ctmd-lightness-slider");
    const lightnessValue = document.getElementById("ctmd-lightness-value");
    const opacitySlider = document.getElementById("ctmd-opacity-slider");
    const opacityValue = document.getElementById("ctmd-opacity-value");
    const saveDerivativeBtn = document.getElementById(
      "ctmd-derivative-save-btn"
    );
    const cancelDerivativeBtn = document.getElementById(
      "ctmd-derivative-cancel-btn"
    );
    const removeLinkBtn = document.getElementById("ctmd-remove-link-btn");
    const parentColorSwatch = document.getElementById(
      "ctmd-parent-color-swatch"
    );
    const previewSwatch = document.getElementById(
      "ctmd-derivative-preview-swatch"
    );
    let activeColorRow = null;
    let allColorsMap = {};

    function updateAllColorsMap() {
      allColorsMap = {};
      const allColorRows = document.querySelectorAll(
        ".ctmd-color-row, .ctmd-special-color-row, .ctmd-add-new-row"
      );
      allColorRows.forEach((row) => {
        const rowData = getRowColorData(row);
        if (rowData.id) {
          allColorsMap[rowData.id] = rowData;
        }
      });
    }

    function updatePreviewSwatch() {
      if (!parentColorSelect.value || !previewSwatch) return;
      const settings = {
        hue: parseInt(hueValue.value, 10) || 0,
        saturation: parseInt(saturationValue.value, 10) || 0,
        lightness: parseInt(lightnessValue.value, 10) || 0,
        opacity: parseInt(opacityValue.value, 10),
      };
      const parentColorString = allColorsMap[parentColorSelect.value].rawValue;
      const parentRgba = colorResolver.resolveColor(
        parentColorString,
        allColorsMap
      );
      const finalRgba = colorResolver.applySettings(parentRgba, settings);
      previewSwatch.style.backgroundColor = `rgba(${finalRgba.r}, ${finalRgba.g}, ${finalRgba.b}, ${finalRgba.a})`;
    }

    function openDerivativeModal() {
      if (!derivativeModal || !modalBackdrop) return;
      derivativeModal.style.display = "block";
      modalBackdrop.style.display = "block";
    }

    function closeDerivativeModal() {
      if (!derivativeModal || !modalBackdrop) return;
      derivativeModal.style.display = "none";
      modalBackdrop.style.display = "none";
      activeColorRow = null;
    }

    function syncInputs(slider, numberInput) {
      const update = () => {
        numberInput.value = slider.value;
        updatePreviewSwatch();
      };
      slider.addEventListener("input", update);
      numberInput.addEventListener("input", () => {
        slider.value = numberInput.value;
        updatePreviewSwatch();
      });
    }
    syncInputs(hueSlider, hueValue);
    syncInputs(saturationSlider, saturationValue);
    syncInputs(lightnessSlider, lightnessValue);
    syncInputs(opacitySlider, opacityValue);

    function getRowColorData(row) {
      const idInput =
        row.querySelector('input[name*="[id]"]') ||
        row.querySelector("input[disabled]");
      const labelInput =
        row.querySelector('input[name*="[label]"]') ||
        row.querySelector('input[disabled][value*="Color"]');
      const colorInput = row.querySelector(".ctmd-color-input");
      let label = labelInput.value;
      const id = idInput.value;
      const idInParens = `(${id})`;
      if (label.endsWith(idInParens)) {
        label = label.substring(0, label.length - idInParens.length).trim();
      }
      return { id: id, label: label, rawValue: colorInput.value };
    }

    parentColorSelect.addEventListener("change", function () {
      const selectedId = this.value;
      if (!allColorsMap[selectedId]) {
        parentColorSwatch.style.backgroundColor = "transparent";
        return;
      }
      const parentColorString = allColorsMap[selectedId].rawValue;
      const resolvedRgba = colorResolver.resolveColor(
        parentColorString,
        allColorsMap
      );
      parentColorSwatch.style.backgroundColor = `rgba(${resolvedRgba.r}, ${resolvedRgba.g}, ${resolvedRgba.b}, ${resolvedRgba.a})`;
      updatePreviewSwatch();
    });

    function populateModal(colorRow) {
      const { id: currentColorId, rawValue: currentColorValue } =
        getRowColorData(colorRow);
      parentColorSelect.innerHTML = "";
      const allColorRows = document.querySelectorAll(
        ".ctmd-color-row, .ctmd-special-color-row"
      );
      allColorRows.forEach((row) => {
        const rowData = getRowColorData(row);
        if (rowData.id && rowData.id !== currentColorId) {
          const option = document.createElement("option");
          option.value = rowData.id;
          option.textContent = rowData.label;
          parentColorSelect.appendChild(option);
        }
      });
      hueSlider.value = hueValue.value = 0;
      saturationSlider.value = saturationValue.value = 0;
      lightnessSlider.value = lightnessValue.value = 0;
      opacitySlider.value = opacityValue.value = 100;
      if (currentColorValue.startsWith("$variable")) {
        removeLinkBtn.style.display = "inline-block";
        try {
          const jsonStr = currentColorValue.substring(
            10,
            currentColorValue.length - 2
          );
          const data = JSON.parse(jsonStr);
          if (data.value && data.value.name)
            parentColorSelect.value = data.value.name;
          if (data.value && data.value.settings) {
            const { hue, saturation, lightness, opacity } = data.value.settings;
            hueSlider.value = hueValue.value = hue || 0;
            saturationSlider.value = saturationValue.value = saturation || 0;
            lightnessSlider.value = lightnessValue.value = lightness || 0;
            opacitySlider.value = opacityValue.value =
              opacity === undefined ? 100 : opacity;
          }
        } catch (e) {
          console.error("Error parsing derivative color string:", e);
        }
      } else {
        removeLinkBtn.style.display = "none";
      }
      parentColorSelect.dispatchEvent(new Event("change"));
    }

    document.querySelectorAll(".ctmd-derivative-link-btn").forEach((button) => {
      button.addEventListener("click", function (e) {
        activeColorRow = e.target.closest("tr");
        updateAllColorsMap();
        populateModal(activeColorRow);
        openDerivativeModal();
      });
    });

    if (cancelDerivativeBtn)
      cancelDerivativeBtn.addEventListener("click", closeDerivativeModal);
    if (modalBackdrop)
      modalBackdrop.addEventListener("click", closeDerivativeModal);

    function updateRowUI(row) {
      const dataInput = row.querySelector(".ctmd-color-input");
      const displayInput = row.querySelector(".ctmd-color-input-display");
      const wrapper = dataInput.closest(".ctmd-color-input-wrapper");
      const swatch = wrapper.querySelector(".ctmd-color-swatch");
      const linkBtn = wrapper.querySelector(".ctmd-derivative-link-btn");

      const isAddNewRow = row.classList.contains("ctmd-add-new-row");
      const isDerivative = dataInput.value.startsWith("$variable");

      displayInput.readOnly = !isAddNewRow || isDerivative;

      if (isDerivative) {
        linkBtn.classList.add("active");
        linkBtn.title = "Edit derivative settings";
        if (swatch.picker) {
          swatch.picker.destroy();
          delete swatch.picker;
        }
        swatch.classList.add("is-derivative");
      } else {
        linkBtn.classList.remove("active");
        linkBtn.title = "Make this a derivative color";
        swatch.classList.remove("is-derivative");
        initializeColorPicker(wrapper);
      }
    }

    function updateRowDisplayValues(row, rgba) {
      const hexValueSpan = row.querySelector(".hex-value");
      const hslValueSmall = row.querySelector(".hsl-value");
      const rgbValueSmall = row.querySelector(".rgb-value");
      const hasAlpha = Math.abs(rgba.a - 1.0) > 0.001;
      const hsl = colorResolver.rgbToHsl(rgba.r, rgba.g, rgba.b);

      hexValueSpan.textContent = hasAlpha
        ? `#${Math.round(rgba.r).toString(16).padStart(2, "0")}${Math.round(
            rgba.g
          )
            .toString(16)
            .padStart(2, "0")}${Math.round(rgba.b)
            .toString(16)
            .padStart(2, "0")}${Math.round(rgba.a * 255)
            .toString(16)
            .padStart(2, "0")}`
        : `#${Math.round(rgba.r).toString(16).padStart(2, "0")}${Math.round(
            rgba.g
          )
            .toString(16)
            .padStart(2, "0")}${Math.round(rgba.b)
            .toString(16)
            .padStart(2, "0")}`;
      hslValueSmall.textContent = hasAlpha
        ? `hsla(${Math.round(hsl.h)}, ${Math.round(hsl.s)}%, ${Math.round(
            hsl.l
          )}%, ${rgba.a.toFixed(2)})`
        : `hsl(${Math.round(hsl.h)}, ${Math.round(hsl.s)}%, ${Math.round(
            hsl.l
          )}%)`;
      rgbValueSmall.textContent = hasAlpha
        ? `rgba(${Math.round(rgba.r)}, ${Math.round(rgba.g)}, ${Math.round(
            rgba.b
          )}, ${rgba.a.toFixed(2)})`
        : `rgb(${Math.round(rgba.r)}, ${Math.round(rgba.g)}, ${Math.round(
            rgba.b
          )})`;
    }

    function updateAllDerivativeDisplays() {
      updateAllColorsMap();
      document
        .querySelectorAll(
          ".ctmd-color-row, .ctmd-special-color-row, .ctmd-add-new-row"
        )
        .forEach((row) => {
          const dataInput = row.querySelector(".ctmd-color-input");
          if (dataInput && dataInput.value.startsWith("$variable")) {
            const resolvedRgba = colorResolver.resolveColor(
              dataInput.value,
              allColorsMap
            );
            const displayInput = row.querySelector(".ctmd-color-input-display");
            const swatch = row.querySelector(".ctmd-color-swatch");
            const linkBtn = row.querySelector(".ctmd-derivative-link-btn");

            let parentName =
              allColorsMap[
                JSON.parse(
                  dataInput.value.substring(10, dataInput.value.length - 2)
                ).value.name
              ].label;
            parentName = parentName.replace(/\s\(.*\)$/, ""); // Strip trailing " (anything)"
            displayInput.value = parentName;
            swatch.style.backgroundColor = `rgba(${resolvedRgba.r}, ${resolvedRgba.g}, ${resolvedRgba.b}, ${resolvedRgba.a})`;
            const parentRgba = colorResolver.resolveColor(
              allColorsMap[
                JSON.parse(
                  dataInput.value.substring(10, dataInput.value.length - 2)
                ).value.name
              ].rawValue,
              allColorsMap
            );
            linkBtn.style.backgroundColor = `rgba(${parentRgba.r}, ${parentRgba.g}, ${parentRgba.b}, ${parentRgba.a})`;

            updateRowDisplayValues(row, resolvedRgba);
          }
        });
    }

    if (saveDerivativeBtn) {
      saveDerivativeBtn.addEventListener("click", function () {
        if (!activeColorRow) return;
        const dataInput = activeColorRow.querySelector(".ctmd-color-input");
        const displayInput = activeColorRow.querySelector(
          ".ctmd-color-input-display"
        );

        const settings = {};
        if (hueValue.value != 0) settings.hue = parseInt(hueValue.value, 10);
        if (saturationValue.value != 0)
          settings.saturation = parseInt(saturationValue.value, 10);
        if (lightnessValue.value != 0)
          settings.lightness = parseInt(lightnessValue.value, 10);
        if (opacityValue.value != 100)
          settings.opacity = parseInt(opacityValue.value, 10);

        const derivativeData = {
          type: "color",
          value: { name: parentColorSelect.value, settings: settings },
        };

        const derivativeString =
          "$variable(" + JSON.stringify(derivativeData) + ")$";
        dataInput.value = derivativeString;

        const parentLabel =
          parentColorSelect.options[parentColorSelect.selectedIndex].text;
        displayInput.value = parentLabel;

        dataInput.dispatchEvent(new Event("change", { bubbles: true }));
        updateAllDerivativeDisplays();
        updateRowUI(activeColorRow);
        closeDerivativeModal();
      });
    }

    if (removeLinkBtn) {
      removeLinkBtn.addEventListener("click", function () {
        if (!activeColorRow) return;
        const dataInput = activeColorRow.querySelector(".ctmd-color-input");
        const displayInput = activeColorRow.querySelector(
          ".ctmd-color-input-display"
        );
        const swatch = activeColorRow.querySelector(".ctmd-color-swatch");
        const linkBtn = activeColorRow.querySelector(
          ".ctmd-derivative-link-btn"
        );
        const newColor = "#000000";

        dataInput.value = newColor;
        displayInput.value = newColor;
        if (swatch) {
          swatch.style.backgroundColor = newColor;
        }
        if (linkBtn) {
          linkBtn.style.backgroundColor = "";
        }

        updateRowDisplayValues(activeColorRow, { r: 0, g: 0, b: 0, a: 1 });

        dataInput.dispatchEvent(new Event("change", { bubbles: true }));
        updateRowUI(activeColorRow);
        updateAllDerivativeDisplays();
        closeDerivativeModal();
      });
    }

    document
      .querySelectorAll(
        ".ctmd-color-row, .ctmd-special-color-row, .ctmd-add-new-row"
      )
      .forEach(updateRowUI);
  }

  // --- Unsaved Changes Warning ---
  const trackedForms = document.querySelectorAll(".ctmd-tracked-form");
  const unsavedWarning = document.getElementById("ctmd-unsaved-warning");
  let isDirty = false;

  function setDirty() {
    if (!isDirty) {
      isDirty = true;
      if (unsavedWarning) unsavedWarning.style.display = "block";
    }
  }

  if (trackedForms.length > 0 && unsavedWarning) {
    trackedForms.forEach(function (form) {
      const formElements = form.querySelectorAll("input, select");
      formElements.forEach(function (element) {
        element.addEventListener("input", setDirty);
        element.addEventListener("change", setDirty);
      });
      form.addEventListener("submit", function () {
        isDirty = false;
      });
    });
  }

  window.addEventListener("beforeunload", function (e) {
    if (isDirty) {
      e.preventDefault();
      e.returnValue =
        "You have unsaved changes. Are you sure you want to leave?";
      return e.returnValue;
    }
  });

  // --- Drag and Drop Sorting ---
  const sortableContainer = document.getElementById("ctmd-sortable-colors");

  if (
    sortableContainer &&
    colorsManagerContainer &&
    !colorsManagerContainer.classList.contains("ctmd-is-locked")
  ) {
    new Sortable(sortableContainer, {
      animation: 150,
      handle: ".ctmd-drag-handle",
      onEnd: function () {
        const orderInput = document.getElementById("ctmd-color-order");
        const rows = sortableContainer.querySelectorAll("tr.ctmd-color-row");
        const newOrder = Array.from(rows).map((row) => row.dataset.colorId);
        orderInput.value = newOrder.join(",");
        setDirty();
      },
    });
  }

  // --- Click to Copy ---
  function copyToClipboard(text, element) {
    const originalText = element.textContent;

    if (navigator.clipboard && window.isSecureContext) {
      navigator.clipboard
        .writeText(text)
        .then(() => {
          element.textContent = "Copied!";
          element.style.color = "#2271b1";
          setTimeout(() => {
            element.textContent = originalText;
            element.style.color = "";
          }, 1000);
        })
        .catch((err) => {
          console.error("Clipboard API failed: ", err);
        });
    } else {
      const textArea = document.createElement("textarea");
      textArea.value = text;
      textArea.style.position = "fixed";
      textArea.style.top = "-9999px";
      textArea.style.left = "-9999px";
      document.body.appendChild(textArea);
      textArea.focus();
      textArea.select();
      try {
        document.execCommand("copy");
        element.textContent = "Copied!";
        element.style.color = "#2271b1";
        setTimeout(() => {
          element.textContent = originalText;
          element.style.color = "";
        }, 1000);
      } catch (err) {
        console.error("Fallback copy failed: ", err);
      }
      document.body.removeChild(textArea);
    }
  }

  const copyElements = document.querySelectorAll(".ctmd-copy-me");
  copyElements.forEach(function (element) {
    element.addEventListener("click", function () {
      copyToClipboard(this.textContent, this);
    });
  });

  // --- SimpleLightbox Initialization ---
  const lightboxGallery = document.querySelector(".ctmd-lightbox-gallery");
  if (lightboxGallery) {
    new SimpleLightbox(".ctmd-lightbox-gallery a", {
      captionDelay: 250,
      animationSpeed: 250,
      fadeSpeed: 300,
    });
  }
});

document.addEventListener('DOMContentLoaded', function() {
    function applyDataColors() {
        const colorElements = document.querySelectorAll('[data-color]');
        colorElements.forEach(function(elem) {
            const colorValue = elem.getAttribute('data-color');
            if (colorValue) {
                elem.style.backgroundColor = colorValue;
            }
        });
    }

    applyDataColors();
});
