import { OSCSSProperties } from "../../types/react";
import {
  IconAnimationType,
  IconOptions,
  IconAnimationOptions,
  IconSize,
} from "../../types/icon";
import { Property } from "csstype";

/**
 * Handler to load FontAwesome custom CSS properties into a classes array and styles object, based on an {@link IconAnimationOptions} object.
 * @package
 * @param animation Animation object to be interpreted, or simple animation slug to play.
 * @param classes Array of classes to be applied to icon
 * @param styles CSSProperties file to apply new styles to
 * @returns
 */
export function parseAnimation(
  animation: IconAnimationOptions | IconAnimationType | undefined,
  classes: string[],
  styles: OSCSSProperties
) {
  if (!animation) return;

  //Handle simple animations
  if (typeof animation === "string") {
    classes.push(`fa-${animation}`);
    return;
  }

  //Handle animation objects
  animation.animationDelay
    ? (styles["--fa-animation-delay"] = animation.animationDelay)
    : null;
  animation.animationDirection
    ? (styles["--fa-animation-direction"] = animation.animationDirection)
    : null;
  animation.animationDuration
    ? (styles["--fa-animation-duration"] = animation.animationDuration)
    : null;
  animation.animationIterationCount
    ? (styles["--fa-animation-iteration-count"] =
        animation.animationIterationCount)
    : null;
  animation.animationTimingFunction
    ? (styles["--fa-animation-timing"] = animation.animationTimingFunction)
    : null;

  //Configure based on animation type
  switch (animation.animation) {
    case "beat":
      classes.push("fa-beat");
      animation.scale ? (styles["--fa-beat-scale"] = animation.scale) : null;
      break;
    case "beat-fade":
      classes.push("fa-beat-fade");
      animation.opacity
        ? (styles["--fa-beat-fade-opacity"] = animation.opacity)
        : null;
      animation.scale
        ? (styles["--fa-beat-fade-scale"] = animation.scale)
        : null;
      break;
    case "bounce":
      classes.push("fa-bounce");
      animation.rebound
        ? (styles["--fa-bounce-rebound"] = animation.rebound)
        : null;
      animation.height
        ? (styles["--fa-bounce-height"] = animation.height)
        : null;
      animation.startScaleX
        ? (styles["--fa-bounce-start-scale-x"] = animation.startScaleX)
        : null;
      animation.startScaleY
        ? (styles["--fa-bounce-start-scale-y"] = animation.startScaleY)
        : null;
      animation.jumpScaleX
        ? (styles["--fa-bounce-jump-scale-x"] = animation.jumpScaleX)
        : null;
      animation.height
        ? (styles["--fa-bounce-jump-scale-y"] = animation.jumpScaleY)
        : null;
      animation.height
        ? (styles["--fa-bounce-land-scale-x"] = animation.landScaleX)
        : null;
      animation.height
        ? (styles["--fa-bounce-land-scale-y"] = animation.landScaleY)
        : null;
      break;
    case "fade":
      classes.push("fa-fade");
      animation.opacity
        ? (styles["--fa-fade-opacity"] = animation.opacity)
        : null;
      break;
    case "flip":
      classes.push("fa-flip");
      animation.flipX ? (styles["--fa-flip-x"] = animation.flipX) : null;
      animation.flipY ? (styles["--fa-flip-y"] = animation.flipY) : null;
      animation.flipZ ? (styles["--fa-flip-z"] = animation.flipZ) : null;
      animation.flipAngle
        ? (styles["--fa-flip-angle"] = animation.flipAngle)
        : null;
      break;
    case "shake":
      classes.push("fa-shake");
      break;
    case "spin":
      classes.push("fa-spin");
      animation.reverse ? classes.push("fa-spin-reverse") : null;
      break;
    case "spin-pulse":
      classes.push("fa-spin-pulse");
      animation.reverse ? classes.push("fa-spin-reverse") : null;
      break;
    default:
      break;
  }
}

/**
 * Handler to parse options object into icon style object.
 * @param options Options to apply
 * @param styles  Style object to modify
 * @returns
 */
export function parseOptions(
  options: IconOptions | undefined,
  styles: OSCSSProperties
) {
  if (!options) return;

  //Handle duotone options.
  options.primaryColour
    ? (styles["--fa-primary-color"] = options.primaryColour)
    : null;
  options.secondaryColour
    ? (styles["--fa-secondary-color"] = options.secondaryColour)
    : null;

  //Opacity
  options.primaryOpacity
    ? (styles["--fa-primary-opacity"] = options.primaryOpacity)
    : null;
  options.secondaryOpacity
    ? (styles["--fa-secondary-opacity"] = options.secondaryOpacity)
    : null;
}

/**
 *
 * @todo figure out way to compare against string literal type itself instead of recreating the list
 * @param size
 */
export function isIconSize(size?: IconSize | Property.FontSize<string | number> | undefined): size is IconSize {
  const validSizes = [
    "2xs",
    "xs",
    "sm",
    "lg",
    "xl",
    "2xl",
    "1x",
    "2x",
    "3x",
    "4x",
    "5x",
    "6x",
    "7x",
    "8x",
    "9x",
    "10x",
  ];

  return validSizes.includes(size as IconSize);
}
