import React, { HTMLProps, ReactNode } from "react";
import classNames from "classnames";
import { Box } from "../Box";
import { bemHOF } from "../../utilities/bem";

const cn = bemHOF("Toggle");

export interface ToggleProps {
  /**
   * Puts Toggle in the on/off state
   */
  checked?: boolean;
  /**
   * Adds classes to the outermost element
   */
  className?: string;
  /**
   * Disables the component
   */
  disabled?: boolean;
  /**
   * Adds an id to the outermost element
   */
  id?: string;
  /**
   * Adds props to the hidden input element within the component
   */
  inputProps?: HTMLProps<HTMLInputElement>;
  /**
   * Called when a user turns the toggle on/off (unless `disabled` is true)
   */
  onChange: (checked: boolean) => void;
  /**
   * The label text
   */
  children?: ReactNode;
  /**
   * Puts the label on either side of the switch
   */
  labelPosition?: "left" | "right";
}

export const Toggle = ({
  checked = false,
  disabled = false,
  id,
  inputProps,
  className,
  onChange,
  children,
  labelPosition = "right",
  ...rest
}: ToggleProps) => {
  const inputRef = React.useRef<HTMLInputElement>(null);

  const handleClick = () => {
    if (!disabled) {
      onChange(!checked);
    }
  };

  return (
    <button
      type="button"
      className={classNames(cn(), cn({ m: labelPosition }), className, {
        isOn: checked,
        isOff: !checked,
      })}
      id={id}
      disabled={disabled}
      role="switch"
      aria-checked={checked}
      onClick={() => {
        if (inputRef.current) {
          inputRef.current.click();
        }
      }}
      {...rest}
    >
      <input
        ref={inputRef}
        disabled={disabled}
        checked={checked}
        type="checkbox"
        onChange={handleClick}
        value={checked ? "on" : "off"}
        hidden
        {...inputProps}
      />
      <Box as="span" className={cn({ e: "track" })} aria-hidden="true">
        <Box as="span" className={cn({ e: "thumb" })} />
      </Box>
      {children && (
        <Box as="span" className={classNames(cn({ e: "label" }))}>
          {children}
        </Box>
      )}
    </button>
  );
};
