import React from 'react';
import styled, { css } from 'styled-components';

import type { JSX } from 'react';

export type SwitchProps = {
  value: boolean;
  onChange: (value: boolean) => void;
  onFocus?: () => void;
  disabled?: boolean;
  stopPropagation?: boolean;
  className?: string;
};

export function Switch({
  value = false,
  disabled = false,
  onChange,
  onFocus,
  stopPropagation = false,
  className,
}: SwitchProps): JSX.Element {
  const handleClick = (event: React.MouseEvent<HTMLDivElement>) => {
    if (disabled) return;
    if (stopPropagation) {
      event.stopPropagation();
    }
    onChange(!value);
  };

  const handleFocus = (event: React.FocusEvent<HTMLDivElement>): void => {
    if (stopPropagation) {
      event.stopPropagation();
    }

    onFocus?.();
  };

  return (
    <SwitchWrapper
      tabIndex={disabled ? -1 : 0}
      onFocus={handleFocus}
      onClick={handleClick}
      role="switch"
      aria-checked={value}
      aria-disabled={disabled}
      selected={value}
      disabled={disabled}
      className={className}
    >
      <Knob selected={value} disabled={disabled} />
    </SwitchWrapper>
  );
}

const SwitchWrapper = styled.div<{ selected: boolean; disabled: boolean }>`
  width: var(--switch-width);
  height: var(--switch-height);
  border-radius: var(--switch-border-radius);
  border: var(--switch-border-width) solid
    ${({ selected, disabled }) =>
      disabled
        ? 'var(--switch-border-color-disabled)'
        : selected
          ? 'var(--switch-border-color-selected)'
          : 'var(--switch-border-color)'};
  background-color: ${({ selected, disabled }) =>
    disabled
      ? selected
        ? 'var(--switch-bg-color-disabled-selected)'
        : 'var(--switch-bg-color-disabled)'
      : selected
        ? 'var(--switch-bg-color-selected)'
        : 'var(--switch-bg-color)'};
  display: flex;
  align-items: center;
  padding: var(--switch-padding);
  cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')};
  transition: var(--switch-bg-transition);

  ${({ selected, disabled }) =>
    !disabled &&
    !selected &&
    css`
      &:hover {
        background-color: var(--switch-bg-color-hover);
        border: var(--switch-border-width) solid var(--switch-border-color-hover);
      }
      &:active {
        background-color: var(--switch-bg-color-pressed);
        border: var(--switch-border-width) solid var(--switch-border-color-pressed);
      }
    `}
`;

const Knob = styled.div<{ selected: boolean; disabled: boolean }>`
  width: var(--switch-knob-width);
  height: var(--switch-knob-height);
  border-radius: var(--switch-knob-border-radius);
  background-color: ${({ selected, disabled }) =>
    disabled
      ? 'var(--switch-knob-bg-color-disabled)'
      : selected
        ? 'var(--switch-knob-bg-color-selected)'
        : 'var(--switch-knob-bg-color)'};
  transform: ${({ selected }) =>
    selected ? 'translateX(var(--switch-knob-width))' : 'translateX(0)'};
  transition: var(--switch-knob-transition);
`;
