import React, { useRef, ReactNode } from 'react';
import {
  TouchableOpacity,
  Animated,
  Platform,
  I18nManager,
} from 'react-native';
import { Box } from '../Box';
import type { ResponsiveValue } from '@shopify/restyle';
import { theme, Theme } from '../../theme/theme';

type SwitchButtonProps = {
  isOn: boolean;
  onToggle: React.Dispatch<React.SetStateAction<boolean>>;
  IconOn?: ReactNode;
  IconOff?: ReactNode;
  onColor?: ResponsiveValue<keyof Theme['colors'], Theme>;
  offColor?: ResponsiveValue<keyof Theme['colors'], Theme>;
  size?: 'small' | 'large';
  disabled?: boolean;
};

const defaultProps = {
  isOn: true,
  onColor: theme.colors.green,
  offColor: theme.colors.gray25,
  IconOn: {},
  IconOff: {},
  size: 'medium',
  labelStyle: {},
  thumbOnStyle: {},
  thumbOffStyle: {},
  trackOnStyle: {},
  trackOffStyle: {},
  icon: null,
  disabled: false,
  animationSpeed: 300,
  useNativeDriver: true,
  circleColor: 'white',
};

export const SwitchButton = (props: SwitchButtonProps) => {
  const { isOn, onToggle, disabled, size, onColor, offColor, IconOn, IconOff } =
    props;
  const colorOn = onColor || defaultProps.onColor;
  const colorOff = offColor || defaultProps.offColor;

  function calculateDimensions(sz: string) {
    switch (sz) {
      case 'small':
        return {
          width: 40,
          padding: 10,
          circleWidth: 15,
          circleHeight: 15,
          translateX: 22,
        };
      case 'large':
        return {
          width: 52,
          padding: 16,
          circleWidth: 28,
          circleHeight: 28,
          translateX: 34,
        };
      default:
        return {
          width: 48,
          height: 24,
          padding: 12,
          circleWidth: 20,
          circleHeight: 20,
          translateX: 26,
        };
    }
  }
  const offsetX = useRef(new Animated.Value(0)).current;
  const dimensions = size
    ? calculateDimensions(size)
    : calculateDimensions(defaultProps.size);

  const createSwitchButtonStyle = () => [
    {
      justifyContent: 'center',
      width: dimensions.width,
      height: dimensions.height,
      borderRadius: 20,
      padding: dimensions.padding,
      backgroundColor: isOn ? colorOn : colorOff,
    },
    isOn ? defaultProps.trackOnStyle : defaultProps.trackOffStyle,
  ];

  const createInsideCircleStyle = () => [
    {
      alignItems: 'center',
      justifyContent: 'center',
      margin: Platform.OS === 'web' ? 0 : 4,
      left: Platform.OS === 'web' ? 4 : 0,
      position: 'absolute',
      backgroundColor: defaultProps.circleColor,
      transform: [{ translateX: offsetX }],
      width: dimensions.circleWidth,
      height: dimensions.circleHeight,
      borderRadius: dimensions.circleWidth / 2,
      shadowColor: '#000',
      shadowOffset: {
        width: 0,
        height: 2,
      },
      shadowOpacity: 0.2,
      shadowRadius: 2.5,
      elevation: 1.5,
    },
    isOn ? defaultProps.thumbOnStyle : defaultProps.thumbOffStyle,
  ];

  let toValue;
  if (!I18nManager.isRTL && isOn) {
    toValue = dimensions.width - dimensions.translateX;
  } else if (I18nManager.isRTL && isOn) {
    toValue = -dimensions.width + dimensions.translateX;
  } else {
    toValue = -1;
  }

  Animated.timing(offsetX, {
    toValue,
    duration: defaultProps.animationSpeed,
    useNativeDriver: true,
  }).start();

  return (
    <Box flexDirection={'row'} alignItems={'center'}>
      <TouchableOpacity
        style={createSwitchButtonStyle()}
        activeOpacity={0.8}
        testID="SwitchButton"
        onPress={() => {
          if (!disabled) {
            onToggle(!isOn);
          }
        }}
      >
        <Animated.View style={createInsideCircleStyle()}>
          {isOn ? IconOn : IconOff}
        </Animated.View>
      </TouchableOpacity>
    </Box>
  );
};
