import type { ReactNode } from 'react';
import React from 'react';
import type { LayoutChangeEvent, TouchableOpacityProps } from 'react-native';
import {
  StyledWrapper,
  StyledPrefixWrapper,
  StyledSuffixWrapper,
  StyledIcon,
} from './StyledFloatingIsland';
import type { IconName } from '../Icon';

interface FloatingIslandProps extends TouchableOpacityProps {
  /**
   * Callback that is called when the floating island is pressed.
   */
  onPress?: () => void;
  /**
   * Children of the floating island.
   */
  children: ReactNode;
  /**
   * Prefix element that is displayed before the children.
   */
  prefix?: IconName | ReactNode;
  /**
   * Suffix element that is displayed after the children.
   */
  suffix?: IconName | ReactNode;
}

const getPrefixOrSuffix = ({
  element,
  isPrefix = true,
}: {
  element: IconName | ReactNode;
  isPrefix: boolean;
}) => {
  const Wrapper = isPrefix ? StyledPrefixWrapper : StyledSuffixWrapper;
  if (typeof element === 'string') {
    return (
      <Wrapper>
        <StyledIcon
          testID={`floating-island-${isPrefix ? 'prefix' : 'suffix'}-icon`}
          size="small"
          icon={element as IconName}
        />
      </Wrapper>
    );
  }

  return <Wrapper>{element}</Wrapper>;
};

const FloatingIsland = ({
  onPress,
  onLayout,
  style,
  children,
  prefix,
  suffix,
  ...props
}: FloatingIslandProps) => {
  const [width, setWidth] = React.useState(0);

  const onWrapperLayout = (event: LayoutChangeEvent) => {
    setWidth(event.nativeEvent.layout.width);

    onLayout?.(event);
  };

  return (
    <StyledWrapper
      {...props}
      onLayout={onWrapperLayout}
      disabled={!onPress}
      onPress={onPress}
      style={[
        style,
        width > 0
          ? {
              transform: [{ translateX: -width / 2 }],
            }
          : undefined,
      ]}
    >
      {prefix && getPrefixOrSuffix({ element: prefix, isPrefix: true })}

      {children}

      {suffix && getPrefixOrSuffix({ element: suffix, isPrefix: false })}
    </StyledWrapper>
  );
};

export default FloatingIsland;
