// Typography engine for ebook rendering
// Feature Registration Pattern implementation

import type { ReaderContext } from "../core/reader-context";

export function init(context: ReaderContext): void {
  let currentConfig: TypographyConfig | null = null;

  context.events.on("reader:loaded", (detail: { container: HTMLElement; config?: Partial<TypographyConfig> }) => {
    currentConfig = {
      readingFont: "literata",
      fontSize: 18,
      lineHeight: 1.6,
      marginTop: 0,
      marginBottom: 16,
      marginLeft: 0,
      marginRight: 0,
      textAlign: "left",
      textIndent: 0,
      hyphenate: false,
      ligatures: true,
      fontSmoothing: "auto",
      ...detail.config,
    };
    applyTypography(detail.container, currentConfig);
  });

  context.events.on("typography:update", (detail: { container: HTMLElement; config: Partial<TypographyConfig> }) => {
    if (currentConfig) {
      currentConfig = updateTypographyConfig(currentConfig, detail.config);
      applyTypography(detail.container, currentConfig);
    }
  });

  context.events.on("typography:measure", (detail: { container: HTMLElement }) => {
    const time = measureReadingTime(detail.container);
    context.events.emit("typography:reading-time", { minutes: time });
  });
}

interface TypographyConfig {
  readingFont:
    | "literata"
    | "crimson"
    | "source-serif"
    | "eb-garamond"
    | "libertinus"
    | "noto-serif"
    | "charis-sil"
    | "ibm-plex";
  fontSize: number;
  lineHeight: number;
  marginTop: number;
  marginBottom: number;
  marginLeft: number;
  marginRight: number;
  textAlign: "left" | "right" | "center" | "justify";
  textIndent: number;
  hyphenate: boolean;
  ligatures: boolean;
  fontSmoothing: "auto" | "antialiased" | "subpixel-antialiased";
}

function applyTypography(
  container: HTMLElement,
  config: TypographyConfig,
): void {
  const content = container.querySelector(".ebook-content");
  if (!content) return;

  const fontStack = getFontStack(config.readingFont);

  content.setAttribute(
    "style",
    `
    font-family: ${fontStack};
    font-size: ${config.fontSize}px;
    line-height: ${config.lineHeight};
    text-align: ${config.textAlign};
    margin-top: ${config.marginTop}px;
    margin-bottom: ${config.marginBottom}px;
    margin-left: ${config.marginLeft}px;
    margin-right: ${config.marginRight}px;
    text-indent: ${config.textIndent}px;
    -webkit-font-smoothing: ${config.fontSmoothing};
    -moz-osx-font-smoothing: auto;
  `,
  );

  if (config.hyphenate) {
    enableHyphenation(container, content as HTMLElement);
  }

  setLigatures(content as HTMLElement, config.ligatures);

  if (config.textAlign === "justify") {
    enableJustification(content as HTMLElement);
  }
}

function getFontStack(fontId: string): string {
  const fonts: Record<string, string> = {
    "literata": "Literata, serif",
    "crimson": "Crimson Text, serif",
    "source-serif": "Source Serif 4, serif",
    "eb-garamond": "EB Garamond, serif",
    "libertinus": "Libertinus Serif, serif",
    "noto-serif": "Noto Serif, serif",
    "charis-sil": "Charis SIL, serif",
    "ibm-plex": "IBM Plex Serif, serif",
  };
  return fonts[fontId] || "Literata, serif";
}

function enableHyphenation(container: HTMLElement, element: HTMLElement): void {
  element.style.hyphens = "auto";
  element.style.hyphenateLimitChars = "6 3 3";

  const lang =
    container.closest("[data-language]")?.getAttribute("data-language") || "en";
  element.setAttribute("lang", lang);
}

function setLigatures(element: HTMLElement, enabled: boolean): void {
  if (enabled) {
    element.style.fontVariantLigatures = "common-ligatures";
    element.style.fontFeatureSettings = '"liga", "dlig"';
  } else {
    element.style.fontVariantLigatures = "no-common-ligatures";
    element.style.fontFeatureSettings = "normal";
  }
}

function enableJustification(element: HTMLElement): void {
  element.style.wordBreak = "normal";
  element.style.overflowWrap = "break-word";
  element.style.wordWrap = "break-word";
  element.style.letterSpacing = "0.01em";
}

function updateTypographyConfig(
  currentConfig: TypographyConfig,
  newConfig: Partial<TypographyConfig>,
): TypographyConfig {
  return { ...currentConfig, ...newConfig };
}

function measureReadingTime(
  container: HTMLElement,
  wordsPerMinute: number = 250,
): number {
  const content = container.querySelector(".ebook-content");
  if (!content) return 0;

  const text = content.textContent || "";
  const words = text.split(/\s+/).length;
  const minutes = words / wordsPerMinute;

  return Math.ceil(minutes);
}

export { applyTypography, getFontStack };