import React from 'react'

import Box from '../box'
import { styled, useStyleConfig, vui } from '../core'
import T from '../t'
import { cs, filterUndefined } from '../utils'
import { spinnerPositionMapping, spinnerSpeedMapping } from './consts'
import { SpinnerProps } from './spinner.types'

export const SpinnerCircle = styled.divBox`
  border-radius: round;
  display: flex;
  flex-shrink: 0;
`

/**
 * Displays a spinning circular element with optional text to signify loading content.
 *
 * Handles different positioning scenarios, speeds and coloring of the circle.
 */
export const Spinner = vui<'div', SpinnerProps>((props, ref) => {
  const {
    className,
    emptyColor,
    size,
    speed: speedProp = 'normal',
    text,
    textPosition = 'bottom',
    thickness,
    ...rest
  } = props

  const styles = useStyleConfig('Spinner', props)
  const isCustomSize = typeof size === 'number'
  const positionProps = spinnerPositionMapping[textPosition]
  const speed = spinnerSpeedMapping[speedProp] ?? speedProp

  const circleProps = filterUndefined({
    borderColor: emptyColor,
    borderWidth: isCustomSize ? (thickness ?? 4) : thickness,
    h: isCustomSize ? size : undefined,
    w: isCustomSize ? size : undefined,
  })

  return (
    <Box
      center
      className={cs('vui-spinner', className)}
      gap={1}
      ref={ref}
      transitionDuration="fast"
      {...positionProps.container}
      {...styles.container}
      {...rest}
    >
      <SpinnerCircle
        animation={`vui-spin ${speed} linear infinite`}
        className="vui-spinnerCircle"
        {...styles.circle}
        {...circleProps}
      />
      {!!text && (
        <T className="vui-spinnerText" {...styles.text}>
          {text}
        </T>
      )}
    </Box>
  )
})

Spinner.displayName = 'Spinner'
export default Spinner
