import type { Transition, Variants } from "framer-motion";

/**
 * Transitions
 * ===================================================================
 */

export const heavySpring = {
  type: "spring",
  damping: 50,
  mass: 25,
  stiffness: 10,
};

export const lightSpring = {
  type: "spring",
  damping: 25,
  mass: 2,
  stiffness: 60,
};

export const defaultSpring = {
  damping: 30,
  mass: 5,
  stiffness: 60,
};

export const defaultTransition: Transition = {
  type: "spring",
  ...defaultSpring,
};

export const staggeredTransition: (
  stagger?: number,
  delay?: number,
) => (custom: number) => Transition =
  (stagger = 0.1, delay = 0) =>
  (custom: number) => ({
    delay: custom * stagger + delay,
    ...defaultSpring,
  });

/**
 * Variants
 * ===================================================================
 */

export const fadeInVariant = createVariant({
  initial: { opacity: 0 },
  animate: { opacity: 1 },
  exit: { opacity: 0 },
});

export const fadeUpVariant = createVariant({
  initial: { opacity: 0, y: 10 },
  animate: { opacity: 1, y: 0 },
  exit: { opacity: 0, y: 10 },
});

export const fadeUpReverseVariant = createVariant({
  ...fadeUpVariant,
  exit: { opacity: 0, y: -10 },
});

export const fadeDownVariant = createVariant({
  initial: { opacity: 0, y: -10 },
  animate: { opacity: 1, y: 0 },
  exit: { opacity: 0, y: -10 },
});

export const fadeDownReverseVariant = createVariant({
  ...fadeDownVariant,
  exit: { opacity: 0, y: 10 },
});

export const fadeLeftVariant = createVariant({
  initial: { opacity: 0, x: -10 },
  animate: { opacity: 1, x: 0 },
  exit: { opacity: 0, x: -10 },
});

export const fadeLeftReverseVariant = createVariant({
  ...fadeLeftVariant,
  exit: { opacity: 0, x: 10 },
});

export const fadeRightVariant = createVariant({
  initial: { opacity: 0, x: 10 },
  animate: { opacity: 1, x: 0 },
  exit: { opacity: 0, x: 10 },
});

export const fadeRightReverseVariant = createVariant({
  ...fadeRightVariant,
  exit: { opacity: 0, x: -10 },
});

export const slideUpVariant = createVariant({
  initial: { y: "100%" },
  animate: { y: 0 },
  exit: { y: "100%" },
});

export const variants = {
  fadeInVariant,
  fadeUpVariant,
  fadeUpReverseVariant,
  fadeDownVariant,
  fadeDownReverseVariant,
  fadeLeftVariant,
  fadeLeftReverseVariant,
  fadeRightVariant,
  fadeRightReverseVariant,
  slideUpVariant,
};

export const staggeredFadeUpVariant = (stagger?: number, delay?: number) =>
  createStaggeredVariant(fadeUpVariant, staggeredTransition(stagger, delay));

export const staggeredFadeDownVariant = (stagger?: number, delay?: number) =>
  createStaggeredVariant(fadeDownVariant, staggeredTransition(stagger, delay));

export const staggeredSlideUpVariant = (stagger?: number, delay?: number) =>
  createStaggeredVariant(slideUpVariant, staggeredTransition(stagger, delay));

/**
 * Helpers
 * ===================================================================
 */

export function createVariant(
  baseVariant: Variants,
  customTransition: Transition = defaultTransition,
): Variants {
  return {
    ...baseVariant,
    animate: {
      ...baseVariant.animate,
      transition: customTransition,
    },
    exit: {
      ...baseVariant.exit,
      transition: customTransition,
    },
  };
}

export function createStaggeredVariant(
  baseVariant: Variants,
  customTransitionFunc: (custom: number) => Transition,
): Variants {
  return {
    initial: baseVariant.initial,
    animate: (custom: number) => ({
      ...baseVariant.animate,
      transition: customTransitionFunc(custom),
    }),
    exit: (custom: number) => ({
      ...baseVariant.exit,
      transition: customTransitionFunc(custom),
    }),
  };
}
