import { customElement, noShadowDOM } from "solid-element";
import { onCleanup } from "solid-js";
import { resolvePath } from "./utils/path";
import { registerStyle } from "./utils/article-style-manager";

const SIDE_CLASSES = new Set(["t", "b", "l", "r", "all"]);
const STYLE_CLASSES = new Set([
  "solid",
  "dashed",
  "dotted",
  "double",
  "groove",
  "ridge",
  "inset",
  "outset",
  "none",
]);
const REPEAT_CLASSES = new Set(["stretch", "repeat", "round", "space"]);

const SIDE_CSS: Record<string, string> = {
  t: "Top",
  b: "Bottom",
  l: "Left",
  r: "Right",
};

function parseSides(classes: string[]): string[] {
  const sides = classes.filter((c) => SIDE_CLASSES.has(c));
  if (sides.length === 0) return ["Top", "Bottom", "Left", "Right"];
  if (sides.includes("all")) return ["Top", "Bottom", "Left", "Right"];
  return sides.map((s) => SIDE_CSS[s]).filter(Boolean);
}

function parseStyle(classes: string[]): string {
  const s = classes.find((c) => STYLE_CLASSES.has(c));
  return s || "solid";
}

function parseRepeat(classes: string[]): string {
  const r = classes.find((c) => REPEAT_CLASSES.has(c));
  return r || "stretch";
}

function isImagePath(value: string): boolean {
  return /^(\.{0,2}\/|[a-zA-Z]:\\|https?:\/\/)|\.(png|jpg|jpeg|gif|svg|webp|bmp)(\?|$)/i.test(
    value,
  );
}

export interface BorderProps {
  width?: string;
  slice?: string;
}

customElement(
  "md-border",
  { width: undefined, slice: "10" },
  (props, { element }) => {
    noShadowDOM();

    const rawValue = element?.textContent?.trim() || "";
    if (element) element.textContent = "";

    const articleEl = element?.closest("article") as HTMLElement;
    const articlePath =
      element?.closest("article[data-src]")?.getAttribute("data-src") || "";

    // Parse classes from the element's className (marked-directive passes
    // attrs.class as the element's className)
    const classList = element?.className ? element.className.split(/\s+/) : [];

    const sides = parseSides(classList);
    const image = isImagePath(rawValue);
    const resolvedSrc = image ? resolvePath(articlePath, rawValue) : "";

    const styles: Partial<CSSStyleDeclaration> = {};

    if (image) {
      const repeat = parseRepeat(classList);
      const borderWidth = props.width || "2mm";
      styles.borderImageSource = `url(${resolvedSrc})`;
      styles.borderImageSlice = props.slice || "10";
      styles.borderImageWidth = borderWidth;
      styles.borderImageRepeat = repeat;
      styles.borderImageOutset = "0";
      (styles as any).borderStyle = "solid";

      const allSides = ["Top", "Bottom", "Left", "Right"];
      for (const side of allSides) {
        if (sides.includes(side)) {
          (styles as any)[`border${side}Width`] = borderWidth;
        } else {
          (styles as any)[`border${side}Width`] = "0";
        }
      }
    } else {
      const color = rawValue || "currentColor";
      const style = parseStyle(classList);
      const borderWidth = props.width || ".2mm";

      for (const side of sides) {
        (styles as any)[`border${side}Width`] = borderWidth;
        (styles as any)[`border${side}Style`] = style;
        (styles as any)[`border${side}Color`] = color;
      }
    }

    const handle = registerStyle({
      key: "border",
      article: articleEl,
      styles,
    });

    onCleanup(() => handle.dispose());

    return null;
  },
);
