---
import type { ImageMetadata } from "astro";
import type { IconProps, IconPropsDirect } from "./Icon.types";
import type { AstroComponentFactory } from "astro/runtime/server/index.js";

type Props = IconProps;

// NOTE: To avoid load compilation times, each used icon id must be listed
// inside `{...}.svg`.
// TODO: Test the performance after Astro upgrades to the Rolldown-powered
// Vite version.
const icons100 = import.meta.glob<{ default: ImageMetadata }>(
  "../../node_modules/@material-symbols/svg-100/rounded/{savings,avg_pace,air,check,close,close_small,chevron_right,add_2,devices,terminal,replay,healing,robot_2,content_copy,archive,http,check_circle,scan,visibility,checklist,search_check,center_focus_strong,find_in_page,database_search,service_toolbox,handyman,tools_power_drill,network_intelligence_update,list_alt_check,text_compare,visibility_lock,file_json,difference,trackpad_input,check_circle,timer}.svg",
);

const icons200 = import.meta.glob<{ default: ImageMetadata }>(
  "../../node_modules/@material-symbols/svg-200/rounded/{add_circle,more_horiz,http,api}.svg",
);

const icons300 = import.meta.glob<{ default: ImageMetadata }>(
  "../../node_modules/@material-symbols/svg-300/rounded/{play_circle,check_circle,chevron_right,robot,face}.svg",
);

const iconsBrands = import.meta.glob<{ default: ImageMetadata }>(
  "../../node_modules/@fortawesome/fontawesome-free/svgs/brands/{apple,linux,windows,aws}.svg",
);

const iconsDev = import.meta.glob<{ default: ImageMetadata }>(
  "../../node_modules/devicon/icons/{azure,googlecloud}/*-plain.svg",
);

const iconsLogo = import.meta.glob<{ default: ImageMetadata }>(
  "../assets/logos/*.svg",
);

let classList: string[] = [];
if ("class" in Astro.props) {
  const { class: className } = Astro.props;
  if (className) classList.push(className);
}

let directProps: IconPropsDirect;
if ("prop" in Astro.props) {
  const { prop } = Astro.props;
  if (typeof prop === "string") {
    directProps = { id: prop };
  } else if (typeof prop === "function") {
    directProps = { Factory: prop };
  } else {
    directProps = prop;
  }
} else {
  directProps = Astro.props;
}

let IconFactory: AstroComponentFactory;
if ("id" in directProps) {
  const { id, style } = directProps;
  const iconFilePath =
    style === "brands"
      ? `../../node_modules/@fortawesome/fontawesome-free/svgs/brands/${id}.svg`
      : style === "dev"
        ? `../../node_modules/devicon/icons/${id}/${id}-plain.svg`
        : style === "logo"
          ? Object.keys(iconsLogo).find((path) =>
              path.includes(`${id}-mono.svg`),
            )
          : `../../node_modules/@material-symbols/svg-${style || "100"}/rounded/${id}.svg`;

  if (!iconFilePath) throw new Error(`Icon ${id} has not been found `);

  const icons =
    style === "brands"
      ? iconsBrands
      : style === "dev"
        ? iconsDev
        : style === "logo"
          ? iconsLogo
          : style === "200"
            ? icons200
            : style === "300"
              ? icons300
              : icons100;

  const iconPath = icons[iconFilePath];
  if (!iconPath)
    throw new Error(`Icon ${id} has not been found at ${iconFilePath}`);

  IconFactory = await iconPath().then(
    (m) => m.default as unknown as AstroComponentFactory,
  );
} else {
  IconFactory = directProps.Factory;
}

const { style } = directProps;
---

<IconFactory class:list={["icon", style && `is-${style}`, ...classList]} />
