import React, { forwardRef, useRef } from 'react';
import type { StyleProp, ViewStyle } from 'react-native';
import { Animated, Modal, Platform } from 'react-native';
import { useDeprecation } from '../../../utils/hooks';
import Box from '../../Box';
import type { IconName } from '../../Icon';
import Portal from '../../Portal';
import type { FABHandles } from '../FAB';
import type { ActionItemProps } from './ActionItem';
import ActionItem from './ActionItem';
import {
  StyledActionGroupContainer,
  StyledBackdrop,
  StyledBackdropPressable,
  StyledContainer,
  StyledContainerInModal,
  StyledFAB,
} from './StyledActionGroup';

export type ActionGroupHandles = {
  showFAB: () => void;
  collapseFAB: () => void;
  hideFAB: () => void;
};

export interface ActionGroupProps {
  /**
   * @deprecated FAB.ActionGroup's `headerTitle` prop will be removed in the next major release. Please remove it.
   *
   * Title of the action group header.
   */
  headerTitle?: string;

  /**
   * This function is called on pressing the FAB button.
   * */
  onPress?: () => void;
  /**
   * This function is called on pressing the FAB backdrop.
   * */
  onBackdropPress?: () => void;
  /**
   * Specify if the FAB button is in active state and the action group is shown.
   * */
  active?: boolean;

  /**
   * Title of the floating action button
   */
  fabTitle?: string;

  /**
   * Icon name of the floating action button
   */
  fabIcon?: IconName;

  /**
   * Additional style.
   */
  style?: StyleProp<ViewStyle>;

  /**
   * Action items of the action group.
   * */
  items?: Array<ActionItemProps>;

  /**
   * Testing id of the component.
   */
  testID?: string;
  /**
   * Supported orientations for the ActionGroup modal, iOS only.
   */
  supportedOrientations?: ('portrait' | 'landscape')[];
}

const ActionGroup = forwardRef<ActionGroupHandles, ActionGroupProps>(
  (
    {
      headerTitle,
      onPress,
      active,
      style,
      items,
      testID,
      fabTitle,
      onBackdropPress,
      fabIcon = 'add',
      supportedOrientations = ['portrait'],
    },
    ref
  ) => {
    useDeprecation(
      `FAB.ActionGroup's headerTitle prop will be removed in the next major release. Please remove it.`,
      headerTitle !== undefined
    );

    const fabRef = useRef<FABHandles>(null);
    const animatedValue = useRef<Animated.Value>(
      new Animated.Value(active ? 1 : 0)
    );

    React.useImperativeHandle(
      ref,
      () => ({
        showFAB: () => fabRef.current?.show(),
        collapseFAB: () => fabRef.current?.collapse(),
        hideFAB: () => fabRef.current?.hide(),
      }),
      [fabRef]
    );

    React.useEffect(() => {
      Animated.spring(animatedValue.current, {
        toValue: active ? 1 : 0,
        useNativeDriver: Platform.OS !== 'web',
      }).start();

      if (active) {
        fabRef.current?.collapse(true, () => {
          fabRef.current?.hide(false);
        });
      } else {
        fabRef.current?.collapse(false);
        fabRef.current?.show();
      }
    }, [active]);

    const actionGroupOpacity = animatedValue.current.interpolate({
      inputRange: [0, 1],
      outputRange: [0, 1],
    });

    return (
      <StyledContainer testID={testID} pointerEvents="box-none" style={style}>
        <Animated.View>
          <StyledFAB
            key="fab"
            testID="fab"
            icon={fabIcon}
            onPress={onPress}
            animated
            active={active}
            title={fabTitle}
            ref={fabRef}
          />
        </Animated.View>
        <Modal
          visible={active}
          animationType="fade"
          transparent
          statusBarTranslucent
          supportedOrientations={supportedOrientations}
        >
          <StyledContainerInModal testID={testID} style={[style]}>
            <StyledBackdropPressable
              testID="back-drop"
              onPress={onBackdropPress}
            >
              {active && (
                <Portal>
                  <StyledBackdrop />
                </Portal>
              )}
            </StyledBackdropPressable>

            <StyledActionGroupContainer
              testID="action-group"
              pointerEvents="box-none"
              style={{
                opacity: actionGroupOpacity,
              }}
            >
              <Box style={{ paddingBottom: 0 }}>
                {items?.map((itemProp, index) => (
                  <ActionItem
                    key={itemProp.key || `${itemProp.icon}_${itemProp.title}`}
                    {...itemProp}
                    index={active ? index : items.length - index}
                    active={active}
                  />
                ))}
              </Box>
            </StyledActionGroupContainer>

            {active && (
              <StyledFAB
                key="fab-in-portal"
                testID="fab-in-portal"
                icon={fabIcon}
                onPress={onPress}
                animated
                active={active}
                title={fabTitle}
              />
            )}
          </StyledContainerInModal>
        </Modal>
      </StyledContainer>
    );
  }
);

ActionGroup.displayName = 'FAB.ActionGroup';

export default ActionGroup;
