import * as React from 'react'
import styled from 'styled-components'
import Icon from '../Icon'

const CaptureArea = styled('label')({
  display: 'inline-block',
  cursor: 'pointer',
  '::after': {
    content: '""',
  },
  'fieldset[disabled] &': {
    cursor: 'not-allowed',
  },
})

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.25rem',
  position: 'relative',
  width: '1.5rem',
  height: '1.5rem',
  minWidth: '1.5rem',
  maxWidth: '1.5rem',
  display: 'inline-flex',
  verticalAlign: 'middle',
  justifyContent: 'center',
  alignItems: 'center',
  transitionProperty: 'border-color',
  [`${Input}:focus ~ &`]: {
    '--color-accent': 'var(--color-active, Highlight)',
  },
  [`${Input}:disabled ~ &`]: {
    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.125rem',
    opacity: 0.5,
    pointerEvents: 'none',
  },
  [`${CaptureArea}: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,
  position: 'relative',
  boxSizing: 'border-box',
  display: 'inline-grid',
  placeContent: 'center',
  borderRadius: 'inherit',
  lineHeight: 1,
  transitionProperty: 'background-color, color, width, height, opacity',
  [`${Input}:checked + ${IndicatorWrapper} &`]: {
    opacity: 1,
    width: '100%',
    height: '100%',
  },
})

const Label = styled('span')({
  color: 'var(--color-accent, blue)',
  width: 'calc(100% - 2.5rem)',
  fontFamily: 'var(--font-family-base, sans-serif)',
  [`${Input}:focus ~ &`]: {
    '--color-accent': 'var(--color-active, Highlight)',
  },
  [`${Input}:disabled ~ &`]: {
    opacity: 0.5,
  },
})

export type Props = Omit<React.HTMLProps<HTMLInputElement>, 'as' | 'className' | 'style'> & {
  /**
   * Short textual description indicating the nature of the component's value.
   */
  label?: React.ReactNode,
  /**
   * Should the label not be visible?
   */
  hiddenLabel?: boolean,
}

/**
 * Component for values that have an on/off state.
 * @see {@link Select} for a similar component suitable for selecting more values.
 * @see {@link RadioButton} for a similar component on selecting a single value among very few choices.
 */
export const Checkbox = React.forwardRef<HTMLInputElement, Props>(({
  label = '',
  disabled = false,
  hiddenLabel = false,
  ...etcProps
}, ref) => (
  <CaptureArea
    style={{
      cursor: disabled ? 'not-allowed' : undefined,
    }}
  >
    <Input
      {...etcProps}
      ref={ref}
      type="checkbox"
      aria-label={label}
      disabled={disabled}
    />
    <IndicatorWrapper>
      <Border />
      <Indicator>
        <Icon name="check" label="" />
      </Indicator>
    </IndicatorWrapper>
    {
      typeof label! !== 'undefined'
      && label !== null
      && !hiddenLabel
      && (
        <>
          {' '}
          <Label>{label}</Label>
        </>
      )
    }
  </CaptureArea>
))

Checkbox.displayName = 'Checkbox'
