import React, { useEffect, useRef, useState } from 'react';
import { View, TouchableWithoutFeedback, Animated, Dimensions, Easing, BackHandler } from 'react-native';
import { PanGestureHandler, PanGestureHandlerStateChangeEvent, State } from 'react-native-gesture-handler';
import { Event } from '../../services';
import { Flex } from '../Flex/native';
import { IActionSheet, IItemsActionSheet, IItemsActionSheetOption } from './ActionSheet.interface';
import {
   Container,
   ItemsContainer,
   Item,
   PanGesture,
   Opacity,
   FontAwesomeIconItem,
   TextItem,
} from './ActionSheet.style';
import { skip } from 'rxjs/operators';

const ActionSheetObs = new Event<IItemsActionSheet>({});

export const ActionSheet: IActionSheet = (props) => {
   let offset = 0;
   const windowHeight = Dimensions.get('window').height;
   const [opened, setOpened] = useState(false);
   const [items, setItems] = useState<Partial<IItemsActionSheet>>({});
   const [heightItems, setHeightItems] = useState(0);
   const add = useRef(new Animated.Value(1)).current;
   const translateY = useRef(new Animated.Value(0)).current;

   const close = (): void => {
      Animated.timing(add, {
         toValue: 1,
         duration: 200,
         useNativeDriver: true,
      }).start(() => {
         setOpened(false);
      });
   };

   useEffect(() => {
      const obs = ActionSheetObs.observable.pipe(skip(1)).subscribe((value) => {
         setItems(value);
         setOpened(true);

         Animated.timing(add, {
            toValue: 0,
            duration: 200,
            useNativeDriver: true,
         }).start();
      });

      return () => obs.unsubscribe();
   }, []);

   useEffect(() => {
      const backAction = (): boolean => {
         if (opened) {
            close();
            return true;
         }
         return false;
      };

      const backHandler = BackHandler.addEventListener('hardwareBackPress', backAction);

      return () => backHandler.remove();
   }, [opened]);

   const animatedEvent = Animated.event(
      [
         {
            nativeEvent: {
               translationY: translateY,
            },
         },
      ],
      {
         useNativeDriver: true,
      },
   );

   const onHandlerStateChange = (event: PanGestureHandlerStateChangeEvent): void => {
      const { translationY, velocityY } = event.nativeEvent;
      offset += translationY;

      if (event.nativeEvent.oldState === State.ACTIVE) {
         if (velocityY > 2000 || translationY > heightItems * 0.4) {
            Animated.timing(translateY, {
               toValue: windowHeight,
               duration: 200,
               useNativeDriver: true,
            }).start(() => {
               add.setValue(1);
               setOpened(false);
            });
         } else {
            Animated.timing(translateY, {
               toValue: 0,
               duration: 200,
               useNativeDriver: true,
            }).start(() => {
               translateY.setValue(0);
            });
         }
      }
   };

   const onPress = (el: IItemsActionSheetOption, index: number): void => {
      items.onPress(el, index);
      close();
   };

   return (
      <>
         {opened && (
            <Container testID="action-sheet">
               <Opacity
                  style={{
                     opacity: Animated.multiply(
                        translateY.interpolate({
                           // x1.5 para dar um efeito mais suave na opacity
                           inputRange: [0, heightItems * 1.5],
                           outputRange: [0.6, 0.0],
                           extrapolate: 'clamp',
                        }),
                        add.interpolate({
                           inputRange: [0, 1],
                           outputRange: [1, 0],
                        }),
                     ),
                  }}
               />
               <PanGestureHandler
                  maxPointers={1}
                  onGestureEvent={animatedEvent}
                  onHandlerStateChange={onHandlerStateChange}
               >
                  <PanGesture
                     style={{
                        transform: [
                           {
                              translateY: Animated.add(
                                 translateY.interpolate({
                                    inputRange: [-windowHeight, 0, windowHeight],
                                    outputRange: [-20, 0, windowHeight],
                                    extrapolate: 'clamp',
                                 }),
                                 add.interpolate({
                                    inputRange: [0, 1],
                                    outputRange: [0, heightItems || windowHeight],
                                    extrapolate: 'clamp',
                                 }),
                              ),
                           },
                        ],
                     }}
                  >
                     <TouchableWithoutFeedback onPress={close}>
                        <View
                           style={{
                              position: 'absolute',
                              width: '100%',
                              height: '100%',
                           }}
                        />
                     </TouchableWithoutFeedback>

                     <ItemsContainer
                        onLayout={(event) => {
                           const { height } = event.nativeEvent.layout;
                           setHeightItems(height);
                        }}
                     >
                        {items.options &&
                           items.options.map((el, index) => (
                              <Item
                                 key={`action-sheet-item-${index}`}
                                 testID={`action-sheet-item-${index}`}
                                 onPress={() => onPress(el, index)}
                              >
                                 <Flex horizontal>
                                    {el.icon && <FontAwesomeIconItem icon={el.icon} color={el.iconColor || '#888'} />}
                                    <TextItem>{el.text}</TextItem>
                                 </Flex>
                              </Item>
                           ))}
                     </ItemsContainer>
                  </PanGesture>
               </PanGestureHandler>
            </Container>
         )}
      </>
   );
};

ActionSheet.show = (options: IItemsActionSheet) => {
   ActionSheetObs.set(options);
};
