import { forwardRef } from "react";

import * as React from "react";

type TypographyProps = {
  as?: React.ElementType;
  size?:
    | "xs"
    | "sm"
    | "base"
    | "lg"
    | "xl"
    | "2xl"
    | "3xl"
    | "4xl"
    | "5xl"
    | "6xl"
    | "7xl"
    | "8xl"
    | "9xl"
    | "10xl"
    | "11xl"
    | "12xl"
    | "13xl"
    | "14xl";
  weight?: "regular" | "normal" | "medium" | "semibold" | "bold" | "black";
  align?: "left" | "center" | "right";
  italic?: boolean;
  underline?: boolean;
  variant?:
    | "H1R"
    | "H1M"
    | "H1B"
    | "H2R"
    | "H2M"
    | "H2B"
    | "H3R"
    | "H3M"
    | "H3B"
    | "H4R"
    | "H4M"
    | "H4B"
    | "H5R"
    | "H5M"
    | "H5B"
    | "BR"
    | "BM"
    | "BB"
    | "FnR"
    | "FnM"
    | "FnB";
  lineHeight?:
    | "3"
    | "4"
    | "5"
    | "6"
    | "6.9"
    | "7"
    | "7.5"
    | "8"
    | "9"
    | "10"
    | "11"
    | "12";
  className?: string;
  children?: React.ReactNode;
} & React.HTMLAttributes<HTMLElement>;

const combineClasses = (...classes: (string | undefined)[]) =>
  classes.filter(Boolean).join(" ");

/**
 *  Headings
 *
 * Desktop:
 * - H1R: `font-size`: `32px`; `font-weight`: `400`; `line-height`: `48px`;
 * - H1M: `font-size`: `32px`; `font-weight`: `500`; `line-height`: `48px`;
 * - H1B: `font-size`: `32px`; `font-weight`: `700`; `line-height`: `48px`;
 * Tablet:
 * - H1R: `font-size`: `24px`; `font-weight`: `400`; `line-height`: `40px`;
 * - H1M: `font-size`: `24px`; `font-weight`: `500`; `line-height`: `40px`;
 * - H1B: `font-size`: `24px`; `font-weight`: `700`; `line-height`: `40px`;
 * Mobile:
 * - H1R: `font-size`: `22px`; `font-weight`: `400`; `line-height`: `32px`;
 * - H1M: `font-size`: `22px`; `font-weight`: `500`; `line-height`: `32px`;
 * - H1B: `font-size`: `22px`; `font-weight`: `700`; `line-height`: `32px`;
 * Desktop:
 * - H2R: `font-size`: `28px`; `font-weight`: `400`; `line-height`: `48px`;
 * - H2M: `font-size`: `28px`; `font-weight`: `500`; `line-height`: `48px`;
 * - H2B: `font-size`: `28px`; `font-weight`: `700`; `line-height`: `48px`;
 * Tablet:
 * - H2R: `font-size`: `20px`; `font-weight`: `400`; `line-height`: `32px`;
 * - H2M: `font-size`: `20px`; `font-weight`: `500`; `line-height`: `32px`;
 * - H2B: `font-size`: `20px`; `font-weight`: `700`; `line-height`: `32px`;
 * Mobile:
 * - H2R: `font-size`: `20px`; `font-weight`: `400`; `line-height`: `32px`;
 * - H2M: `font-size`: `20px`; `font-weight`: `500`; `line-height`: `32px`;
 * - H2B: `font-size`: `20px`; `font-weight`: `700`; `line-height`: `32px`;
 * Desktop:
 * - H3R: `font-size`: `24px`; `font-weight`: `400`; `line-height`: `40px`;
 * - H3M: `font-size`: `24px`; `font-weight`: `500`; `line-height`: `40px`;
 * - H3B: `font-size`: `24px`; `font-weight`: `700`; `line-height`: `40px`;
 * Tablet:
 * - H3R: `font-size`: `18px`; `font-weight`: `400`; `line-height`: `32px`;
 * - H3M: `font-size`: `18px`; `font-weight`: `500`; `line-height`: `32px`;
 * - H3B: `font-size`: `18px`; `font-weight`: `700`; `line-height`: `32px`;
 * Mobile:
 * - H3R: `font-size`: `16px`; `font-weight`: `400`; `line-height`: `24px`;
 * - H3M: `font-size`: `16px`; `font-weight`: `500`; `line-height`: `24px`;
 * - H3B: `font-size`: `16px`; `font-weight`: `700`; `line-height`: `24px`;
 * Desktop:
 * - H4R: `font-size`: `20px`; `font-weight`: `400`; `line-height`: `32px`;
 * - H4M: `font-size`: `20px`; `font-weight`: `500`; `line-height`: `32px`;
 * - H4B: `font-size`: `20px`; `font-weight`: `700`; `line-height`: `32px`;
 * Tablet:
 * - H4R: `font-size`: `16px`; `font-weight`: `400`; `line-height`: `24px`;
 * - H4M: `font-size`: `16px`; `font-weight`: `500`; `line-height`: `24px`;
 * - H4B: `font-size`: `16px`; `font-weight`: `700`; `line-height`: `24px`;
 * Mobile:
 * - H4R: `font-size`: `14px`; `font-weight`: `400`; `line-height`: `24px`;
 * - H4M: `font-size`: `14px`; `font-weight`: `500`; `line-height`: `24px`;
 * - H4B: `font-size`: `14px`; `font-weight`: `700`; `line-height`: `24px`;
 * Desktop:
 * - H5R: `font-size`: `16px`; `font-weight`: `400`; `line-height`: `24px`;
 * - H5M: `font-size`: `16px`; `font-weight`: `500`; `line-height`: `24px`;
 * - H5B: `font-size`: `16px`; `font-weight`: `700`; `line-height`: `24px`;
 * Tablet:
 * - H5R: `font-size`: `14px`; `font-weight`: `400`; `line-height`: `24px`;
 * - H5M: `font-size`: `14px`; `font-weight`: `500`; `line-height`: `24px`;
 * - H5B: `font-size`: `14px`; `font-weight`: `700`; `line-height`: `24px`;
 * Mobile:
 * - H5R: `font-size`: `14px`; `font-weight`: `400`; `line-height`: `24px`;
 * - H5M: `font-size`: `14px`; `font-weight`: `500`; `line-height`: `24px`;
 * - H5B: `font-size`: `14px`; `font-weight`: `700`; `line-height`: `24px`;
 *
 * Body
 *
 * Desktop:
 * - BR: `font-size`: `14px`; `font-weight`: `400`; `line-height`: `24px`;
 * - BM: `font-size`: `14px`; `font-weight`: `500`; `line-height`: `24px`;
 * - BB: `font-size`: `14px`; `font-weight`: `700`; `line-height`: `24px`;
 * Tablet:
 * - BR: `font-size`: `12px`; `font-weight`: `400`; `line-height`: `20px`;
 * - BM: `font-size`: `12px`; `font-weight`: `500`; `line-height`: `20px`;
 * - BB: `font-size`: `12px`; `font-weight`: `700`; `line-height`: `20px`;
 * Mobile:
 * - BR: `font-size`: `12px`; `font-weight`: `400`; `line-height`: `20px`;
 * - BM: `font-size`: `12px`; `font-weight`: `500`; `line-height`: `20px`;
 * - BB: `font-size`: `12px`; `font-weight`: `700`; `line-height`: `20px`;
 *
 * footnote
 *
 * Desktop:
 * - FnR: `font-size`: `12px`; `font-weight`: `400`; `line-height`: `20px`;
 * - FnM: `font-size`: `12px`; `font-weight`: `500`; `line-height`: `20px`;
 * - FnB: `font-size`: `12px`; `font-weight`: `700`; `line-height`: `20px`;
 * Tablet:
 * - FnR: `font-size`: `10px`; `font-weight`: `400`; `line-height`: `16px`;
 * - FnM: `font-size`: `10px`; `font-weight`: `500`; `line-height`: `16px`;
 * - FnB: `font-size`: `10px`; `font-weight`: `700`; `line-height`: `16px`;
 * Mobile:
 * - FnR: `font-size`: `10px`; `font-weight`: `400`; `line-height`: `16px`;
 * - FnM: `font-size`: `10px`; `font-weight`: `500`; `line-height`: `16px`;
 * - FnB: `font-size`: `10px`; `font-weight`: `700`; `line-height`: `16px`;
 *
 */

const typographyStyles = (props: TypographyProps) => {
  const baseStyles = "";
  const variants = {
    size: {
      xs: "text-sm",
      sm: "text-sm",
      base: "text-base",
      lg: "text-lg",
      xl: "text-xl",
      "2xl": "text-2xl",
      "3xl": "text-3xl",
      "4xl": "text-4xl",
      "5xl": "text-5xl",
      "6xl": "text-6xl",
      "7xl": "text-7xl",
      "8xl": "text-8xl",
      "9xl": "text-9xl",
      "10xl": "text-10xl",
      "11xl": "text-11xl",
      "12xl": "text-12xl",
      "13xl": "text-13xl",
      "14xl": "text-14xl",
    },
    weight: {
      regular: "font-thin",
      normal: "font-normal",
      medium: "font-medium",
      semibold: "font-semibold",
      bold: "font-bold",
      black: "font-black",
    },
    align: {
      left: "text-left",
      center: "text-center",
      right: "text-right",
    },
    italic: {
      true: "italic",
    },
    underline: {
      true: "underline underline-offset-2",
    },
    variant: {
      H1R: "text-[22px] md:text-2xl lg:text-[32px] 2xl:text-[42px] font-normal",
      H1M: "text-[22px] md:text-2xl lg:text-[32px] 2xl:text-[42px] font-medium",
      H1B: "text-[22px] md:text-2xl lg:text-[32px] 2xl:text-[42px] font-bold",
      H2R: "text-xl md:text-xl lg:text-[28px] font-normal",
      H2M: "text-xl md:text-xl lg:text-[28px] font-medium",
      H2B: "text-xl md:text-xl lg:text-[28px] font-bold",
      H3R: "text-base md:text-lg lg:text-2xl font-normal",
      H3M: "text-base md:text-lg lg:text-2xl font-medium",
      H3B: "text-base md:text-lg lg:text-2xl font-bold",
      H4R: "text-base lg:text-xl font-normal",
      H4M: "text-base lg:text-xl font-medium",
      H4B: "text-base lg:text-xl font-bold",
      H5R: "text-base font-normal",
      H5M: "text-base font-medium",
      H5B: "text-base font-bold",
      BR: "text-base sm:text-sm font-normal",
      BM: "text-base sm:text-sm font-medium",
      BB: "text-base sm:text-sm font-bold",
      FnR: "text-xs font-normal",
      FnM: "text-xs font-medium",
      FnB: "text-xs font-bold",
    },
    lineHeight: {
      "3": "leading-3",
      "4": "leading-4",
      "5": "leading-5",
      "6": "leading-6",
      "6.9": "leading-6.9",
      "7": "leading-7",
      "7.5": "leading-7.5",
      "8": "leading-8",
      "9": "leading-9",
      "10": "leading-10",
      "11": "leading-11",
      "12": "leading-12",
    },
  };

  const {
    size = "base",
    weight,
    align,
    italic,
    underline,
    variant,
    lineHeight,
    className,
  } = props;

  const classes = [
    baseStyles,
    size && variants.size[size],
    weight && variants.weight[weight],
    align && variants.align[align],
    italic ? variants.italic.true : undefined,
    underline ? variants.underline.true : undefined,
    variant && variants.variant[variant],
    lineHeight && variants.lineHeight[lineHeight],
    className,
  ];

  return combineClasses(...classes);
};

export const Typography = forwardRef<HTMLElement, TypographyProps>(
  (
    {
      as = "span",
      align,
      size,
      italic,
      underline,
      weight,
      variant,
      lineHeight,
      className,
      children,
      ...props
    },
    ref
  ) => {
    const Component = as as React.ElementType;

    return (
      <Component
        ref={ref}
        className={typographyStyles({
          size,
          weight,
          italic,
          underline,
          align,
          variant,
          lineHeight,
          className,
        })}
        {...props}
      >
        {children}
      </Component>
    );
  }
);

Typography.displayName = "Typography";
