import {
  FaSymbol,
  FlipProp,
  IconDefinition,
  IconProp,
  PullProp,
  RotateProp,
  SizeProp,
  Transform,
} from "@fortawesome/fontawesome-svg-core";
import { type JSX } from "solid-js";

export interface FontAwesomeIconProps
  extends Omit<
    JSX.SvgSVGAttributes<SVGSVGElement>,
    "children" | "mask" | "transform"
  > {
  icon: IconDefinition;
  mask?: IconProp;
  maskId?: string;
  color?: string;
  spin?: boolean;
  spinPulse?: boolean;
  spinReverse?: boolean;
  pulse?: boolean;
  beat?: boolean;
  fade?: boolean;
  beatFade?: boolean;
  bounce?: boolean;
  shake?: boolean;
  flash?: boolean;
  border?: boolean;
  fixedWidth?: boolean;
  inverse?: boolean;
  listItem?: boolean;
  flip?: FlipProp;
  size?: SizeProp;
  pull?: PullProp;
  rotation?: RotateProp;
  transform?: string | Transform;
  symbol?: FaSymbol;
  style?: JSX.CSSProperties;
  tabIndex?: number;
  title?: string;
  titleId?: string;
  swapOpacity?: boolean;
}

const idPool = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
function nextUniqueId() {
  let size = 12;
  let id = "";

  while (size-- > 0) {
    id += idPool[(Math.random() * 62) | 0];
  }

  return id;
}

function Path(props: { d: string | string[] }) {
  return (
    <>
      {typeof props.d === "string" ? (
        <path fill="currentColor" d={props.d} />
      ) : (
        <>
          <path class="fa-secondary" fill="currentColor" d={props.d[0]} />
          <path class="fa-primary" fill="currentColor" d={props.d[1]} />
        </>
      )}
    </>
  );
}

export function FontAwesomeIcon(props: FontAwesomeIconProps) {
  const titleId = () =>
    props.title
      ? "svg-inline--fa-title-".concat(props.titleId || nextUniqueId())
      : undefined;
  // Get CSS class list from the props object
  function attributes() {
    const defaultClasses = {
      "svg-inline--fa": true,
      [`fa-${props.icon.iconName}`]: true,
      [props.class ?? ""]:
        typeof props.class !== "undefined" && props.class !== null,
      ...props.classList,
    };

    // map of CSS class names to properties
    const faClasses = {
      "fa-beat": props.beat,
      "fa-fade": props.fade,
      "fa-beat-fade": props.beatFade,
      "fa-bounce": props.bounce,
      "fa-shake": props.shake,
      "fa-flash": props.flash,
      "fa-spin": props.spin,
      "fa-spin-reverse": props.spinReverse,
      "fa-spin-pulse": props.spinPulse,
      "fa-pulse": props.pulse,
      "fa-fw": props.fixedWidth,
      "fa-inverse": props.inverse,
      "fa-border": props.border,
      "fa-li": props.listItem,
      "fa-flip": typeof props.flip !== "undefined" && props.flip !== null,
      "fa-flip-horizontal":
        props.flip === "horizontal" || props.flip === "both",
      "fa-flip-vertical": props.flip === "vertical" || props.flip === "both",
      [`fa-${props.size}`]:
        typeof props.size !== "undefined" && props.size !== null,
      [`fa-rotate-${props.rotation}`]:
        typeof props.rotation !== "undefined" && props.size !== null,
      [`fa-pull-${props.pull}`]:
        typeof props.pull !== "undefined" && props.pull !== null,
      "fa-swap-opacity": props.swapOpacity,
    };

    const attributes = {
      focusable: !!props.title,
      "aria-hidden": !props.title,
      role: "img",
      xmlns: "http://www.w3.org/2000/svg",
      "aria-labelledby": titleId(),
      "data-prefix": props.icon.prefix,
      "data-icon": props.icon.iconName,
      "data-fa-transform": props.transform,
      "data-fa-mask": props.mask,
      "data-fa-mask-id": props.maskId,
      "data-fa-symbol": props.symbol,
      tabIndex: props.tabIndex,
      classList: { ...defaultClasses, ...faClasses },
      color: props.color,
      style: props.style,
      viewBox: `0 0 ${props.icon.icon[0]} ${props.icon.icon[1]}`,
    } as const;

    // return the complete class list
    return attributes;
  }

  return (
    <svg {...attributes()}>
      {/* <Show when={props.title}>
        <title id={titleId()}>{props.title}</title>
      </Show> */}
      <Path d={props.icon.icon[4]} />
    </svg>
  );
}
