import * as React from 'react'
import * as PropTypes from 'prop-types'
import styled from 'styled-components'
import stringify from '../../services/stringify'

const Base = styled('div')({
  display: 'block',
})

const CaptureArea = styled('label')({
  marginTop: '0.25rem',
  '::after': {
    content: '""',
    clear: 'both',
  },
})

CaptureArea.displayName = 'label'

const Input = styled('input')({
  position: 'absolute',
  left: -999999,
  width: 1,
  height: 1,
})

Input.displayName = 'input'

const IndicatorWrapper = styled('span')({
  borderColor: 'var(--color-accent, blue)',
  boxSizing: 'border-box',
  backgroundColor: 'transparent',
  borderRadius: '0.75rem',
  position: 'relative',
  width: '1.5rem',
  height: '1.5rem',
  minWidth: '1.5rem',
  maxWidth: '1.5rem',
  display: 'inline-flex',
  verticalAlign: 'top',
  justifyContent: 'center',
  alignItems: 'center',
  cursor: 'pointer',
  transitionProperty: 'border-color',
  [`${Input}:focus ~ &`]: {
    '--color-accent': 'var(--color-active, Highlight)',
  },
  [`${Input}:disabled ~ &`]: {
    cursor: 'not-allowed',
    opacity: 0.5,
  },
})

const Border = styled('span')({
  borderColor: 'var(--color-accent, blue)',
  boxSizing: 'border-box',
  display: 'inline-block',
  borderWidth: '0.125rem',
  borderStyle: 'solid',
  position: 'absolute',
  top: 0,
  left: 0,
  width: '100%',
  height: '100%',
  borderRadius: 'inherit',
  transitionProperty: 'border-color',
  '::before': {
    position: 'absolute',
    top: 0,
    left: 0,
    width: '100%',
    height: '100%',
    content: "''",
    borderRadius: '0.75rem',
    opacity: 0.5,
    pointerEvents: 'none',
  },
  [`${Base}:focus-within &::before`]: {
    boxShadow: '0 0 0 0.375rem var(--color-accent, blue)',
  },
})

const Indicator = styled('span')({
  backgroundColor: 'var(--color-accent, blue)',
  color: 'var(--color-bg, white)',
  width: 0,
  height: 0,
  opacity: 0,
  boxSizing: 'border-box',
  display: 'inline-grid',
  placeContent: 'center',
  borderRadius: '50%',
  transitionProperty: 'background-color, color, width, height, opacity',
  [`${Input}:checked + ${IndicatorWrapper} &`]: {
    width: `${(100 * 2) / 3}%`,
    height: `${(100 * 2) / 3}%`,
    opacity: 1,
  },
})

const Label = styled('span')({
  display: 'block',
  verticalAlign: 'top',
  float: 'right',
  width: 'calc(100% - 2.5rem)',
  fontFamily: 'var(--font-family-base)',
  pointerEvents: 'none',
})

const LabelContent = styled('span')({
  display: 'inline',
  pointerEvents: 'auto',
})

const propTypes = {
  /**
   * Group where the component belongs.
   */
  name: PropTypes.string.isRequired,
  /**
   * Short textual description indicating the nature of the component's value.
   */
  label: PropTypes.any,
}

type Props = PropTypes.InferProps<typeof propTypes>

/**
 * Component for values which are to be selected from a few list of options.
 * @see {@link Checkbox} for a similar component on selecting values among very few choices.
 * @see {@link Select} for a similar component suitable for selecting more values.
 * @type {React.ComponentType<{readonly label?: string, readonly name?: string} & React.ClassAttributes<unknown>>}
 */
const RadioButton = React.forwardRef<HTMLInputElement, Props>(
  (
    { label = '', name, ...etcProps },
    ref
  ) => (
    <Base>
      <CaptureArea>
        <Input {...etcProps} ref={ref} name={name} type="radio" />
        <IndicatorWrapper>
          <Border />
          <Indicator />
        </IndicatorWrapper>
        {typeof label! !== 'undefined' && label !== null && ' '}
        <Label>
          <LabelContent>{stringify(label)}</LabelContent>
        </Label>
      </CaptureArea>
    </Base>
  )
)

RadioButton.propTypes = propTypes

RadioButton.displayName = 'RadioButton'

export default RadioButton
