import classNames from 'classnames';
import {
  type ChangeEventHandler,
  type CSSProperties,
  type FocusEventHandler,
  type FunctionComponent,
  type KeyboardEventHandler,
  memo,
  type MouseEventHandler,
  type Ref,
  type TouchEventHandler,
} from 'react';

import { ExclamationSquareFill } from '@/icons';

import styles from './Tile.module.scss';

interface Props {
  'aria-label': string;
  autoFocus?: boolean;
  canShowPoints?: boolean;
  character?: string;
  className?: string;
  disabled?: boolean;
  highlighted?: boolean;
  inputRef: Ref<HTMLInputElement>;
  isBlank?: boolean;
  isValid?: boolean;
  placeholder?: string;
  points?: number;
  pointsFormatted?: string;
  pointsStyle?: CSSProperties;
  raised?: boolean;
  style?: CSSProperties;
  tabIndex?: number;
  onChange?: ChangeEventHandler<HTMLInputElement>;
  onFocus?: FocusEventHandler<HTMLInputElement>;
  onKeyDown?: KeyboardEventHandler<HTMLInputElement>;
  onMouseDown?: MouseEventHandler<HTMLInputElement>;
  onTouchStart?: TouchEventHandler<HTMLInputElement>;
}

const TilePureBase: FunctionComponent<Props> = ({
  'aria-label': ariaLabel,
  autoFocus,
  canShowPoints,
  character,
  className,
  disabled,
  highlighted,
  inputRef,
  isBlank,
  isValid,
  placeholder,
  points,
  pointsFormatted,
  pointsStyle,
  raised,
  style,
  tabIndex,
  onChange,
  onFocus,
  onKeyDown,
  onMouseDown,
  onTouchStart,
}) => (
  <div
    className={classNames(styles.tile, className, {
      [styles.blank]: isBlank,
      [styles.empty]: !character,
      [styles.invalid]: !isValid,
      [styles.highlighted]: highlighted,
      [styles.points1]: points === 1,
      [styles.points2]: points === 2,
      [styles.points3]: points === 3,
      [styles.points4]: points === 4,
      [styles.points5]: typeof points === 'number' && points >= 5,
      [styles.raised]: raised,
    })}
    role={highlighted ? 'mark' : undefined}
    style={style}
  >
    {character || placeholder}

    {!disabled && (
      <input
        aria-label={ariaLabel}
        autoCapitalize="none"
        autoComplete="off"
        autoCorrect="off"
        autoFocus={autoFocus}
        className={styles.input}
        disabled={disabled}
        ref={inputRef}
        spellCheck={false}
        tabIndex={tabIndex}
        value={character || ''}
        onChange={onChange}
        onFocus={onFocus}
        onKeyDown={onKeyDown}
        onMouseDown={onMouseDown}
        onTouchStart={onTouchStart}
      />
    )}

    {canShowPoints && (
      <span className={styles.points} style={pointsStyle}>
        {pointsFormatted}
      </span>
    )}

    {!isValid && <ExclamationSquareFill aria-hidden="true" className={styles.alert} role="img" />}
  </div>
);

export const TilePure = memo(TilePureBase);
