import * as React from 'react'
import invariant from 'tiny-invariant'
import { Box, PolymorphicComponentProps } from 'react-polymorphic-box'

import './AspectRatio.css'

const defaultElement = 'div'

export type AspectRatioPropsBase = {
  /** The ratio of the component's width relative to its height. */
  x: number
  /** The ratio of the component's height relative to its width. */
  y: number
}

export type AspectRatioProps<
  E extends React.ElementType
> = PolymorphicComponentProps<E, AspectRatioPropsBase>

/**
 * `<View>` sized with a specified aspect ratio.
 *
 * @example
 * With a 16:9 ratio:
 * <AspectRatio x={16} y={9}>Content</AspectRatio>
 */
export const AspectRatio: <E extends React.ElementType = typeof defaultElement>(
  props: AspectRatioProps<E>,
) => React.ReactElement | null = React.forwardRef(
  <E extends React.ElementType = typeof defaultElement>(
    { x, y, children, ...props }: AspectRatioProps<E>,
    innerRef: typeof props.ref,
  ) => {
    invariant(x > 0, 'Prop x must be a number greater than 0.')
    invariant(y >= 0, 'Prop y must be a number greater than or equal to 0.')

    return (
      <Box
        ref={innerRef}
        as={defaultElement}
        data-siamese-aspect-ratio=""
        {...props}
      >
        <div
          data-siamese-aspect-ratio-spacer=""
          aria-hidden={true}
          style={{ paddingTop: `${(y / x) * 100}%` }}
        />
        <div data-siamese-aspect-ratio-inner="">{children}</div>
      </Box>
    )
  },
)

// @ts-expect-error: Component type does not currently include displayName
AspectRatio.displayName = 'AspectRatio'
