import React, { useCallback, useContext, useEffect, useRef } from 'react';
import {
  Animated,
  Easing,
  KeyboardAvoidingView,
  Platform,
  Pressable,
  StyleSheet,
  View,
  Modal as ModalRN,
  BackHandler,
} from 'react-native';

import { ApplicationContext, MiniAppContext } from '../Context';
import { Styles } from '../Consts';
import Navigation from './Navigation';
import { ModalParams } from './types';
import BottomSheet from './BottomSheet';
import { runOnJS } from 'react-native-reanimated';

const ModalScreen: React.FC<any> = props => {
  if (props.route?.params?.isBottomSheet) {
    return <BottomSheet {...props} />;
  }
  return <Modal {...props} />;
};

const Modal: React.FC<ModalParams> = props => {
  const { navigator } = useContext(ApplicationContext);
  const context = useContext<any>(MiniAppContext);
  const modalParams = useRef<any>(undefined);
  const {
    screen,
    barrierDismissible,
    modalStyle,
    useNativeModal = false,
  } = props.route.params;
  const Component = useRef(screen).current;
  const opacity = useRef(new Animated.Value(0)).current;
  const scale = useRef(new Animated.Value(0.8)).current;

  const navigation = new Navigation(props.navigation);
  const params = {
    ...props.route.params,
    navigation,
  };
  delete params.screen;
  let Container: any = View;
  if (useNativeModal) {
    Container = ModalRN;
  }

  if (screen != null) {
    const screenProps = screen?.()?.props || {};
    modalParams.current = {
      title: screenProps?.title || '',
      description: screenProps?.description || '',
    };
  }

  useEffect(() => {
    const item: any = {
      screenName: params.screen,
      componentName: 'Modal',
      ...modalParams.current,
    };
    context?.autoTracking?.({
      ...context,
      ...item,
    });
  }, [context, params.screen]);

  useEffect(() => {
    Animated.parallel([
      Animated.timing(opacity, {
        toValue: 1,
        duration: 250,
        useNativeDriver: true,
      }),
      Animated.timing(scale, {
        toValue: 1,
        duration: 250,
        easing: Easing.bezier(0.2, 0.0, 0, 1.0),
        useNativeDriver: true,
      }),
    ]).start();

    return () => {
      props.route.params?.onDismiss?.();
    };
  }, [opacity, props.route.params, scale]);

  const onDismiss = useCallback(
    (callback = () => {}, preventClose = false) => {
      if (preventClose) {
        return;
      }
      Animated.parallel([
        Animated.timing(opacity, {
          toValue: 0,
          duration: 200,
          useNativeDriver: true,
        }),
        Animated.timing(scale, {
          toValue: 0.8,
          duration: 200,
          easing: Easing.linear,
          useNativeDriver: true,
        }),
      ]).start(() => {
        navigator?.pop();
        runOnJS(callback)();
      });
    },
    [navigator, opacity, scale],
  );

  useEffect(() => {
    const backHandler = BackHandler.addEventListener(
      'hardwareBackPress',
      () => {
        onDismiss(undefined, barrierDismissible);
        return true;
      },
    );
    return () => backHandler.remove();
  }, [barrierDismissible, onDismiss]);

  return (
    <Container
      transparent
      visible={true}
      onRequestClose={onDismiss}
      style={StyleSheet.absoluteFillObject}
      isModalKit={true}
    >
      <KeyboardAvoidingView
        style={Styles.flexCenter}
        behavior={Platform.OS === 'ios' ? 'padding' : undefined}
      >
        <Pressable
          style={StyleSheet.absoluteFillObject}
          onPress={() => onDismiss(undefined, barrierDismissible)}
        >
          <Animated.View style={[styles.overlayContent, { opacity }]} />
        </Pressable>
        <Animated.View
          style={[
            {
              opacity,
              transform: [{ scale }],
            },
            modalStyle,
          ]}
        >
          <Component {...params} onRequestClose={onDismiss} />
        </Animated.View>
      </KeyboardAvoidingView>
    </Container>
  );
};

const styles = StyleSheet.create({
  overlayContent: {
    flex: 1,
    backgroundColor: 'rgba(0, 0, 0, 0.6)',
  },
});

export default ModalScreen;
