import { useTheme } from '@emotion/react';
import React, { useEffect, useState } from 'react';

import { Animated, Easing, TouchableWithoutFeedback } from 'react-native';

import type { ReactElement } from 'react';
import type { StyleProp, ViewStyle } from 'react-native';
import SelectorSwitch from './SelectorSwitch';
import type { Variant } from './StyledSwitch';
import { StyledKnot, StyledWrapper } from './StyledSwitch';

export interface SwitchProps {
  /**
   * Control whether the switch is checked
   */
  checked?: boolean;
  /**
   * Whether the switch is disabled
   */
  disabled?: boolean;
  /**
   * Event handler.
   */
  onPress?: () => void;
  /**
   * Additional style.
   */
  style?: StyleProp<ViewStyle>;
  /**
   * Testing id of the component.
   */
  testID?: string;
}

const getVariant = ({
  disabled,
  checked,
}: {
  disabled: boolean;
  checked: boolean;
}): Variant => {
  if (disabled) {
    return checked ? 'disabled-checked' : 'disabled-unchecked';
  }
  return checked ? 'checked' : 'unchecked';
};

const Switch = ({
  disabled = false,
  checked = false,
  onPress,
  style,
  testID,
}: SwitchProps): ReactElement => {
  const theme = useTheme();
  const variant = getVariant({ disabled, checked });

  const offset = checked
    ? (theme.__hd__.switch.sizes.width - theme.__hd__.switch.sizes.thumb) / 2 +
      theme.__hd__.switch.sizes.thumb / 2
    : 0;

  const [animatedOffset] = useState(() => new Animated.Value(offset));

  useEffect(() => {
    Animated.timing(animatedOffset, {
      toValue: offset,
      easing: Easing.inOut(Easing.cubic),
      duration: 200,
      useNativeDriver: false,
    }).start();
  }, [checked]);
  return (
    <TouchableWithoutFeedback
      testID={testID}
      onPress={onPress}
      disabled={disabled}
    >
      <StyledWrapper themeVariant={variant} style={style}>
        <StyledKnot style={{ left: animatedOffset }} />
      </StyledWrapper>
    </TouchableWithoutFeedback>
  );
};

export default Object.assign(Switch, {
  Selector: SelectorSwitch,
});
