import CameraRoll from '@react-native-community/cameraroll';
import {useBottomTabBarHeight} from '@react-navigation/bottom-tabs';
import {RouteProp} from '@react-navigation/core';
import {useFocusEffect} from '@react-navigation/native';
import {StackNavigationProp} from '@react-navigation/stack';
import React, {createRef, useCallback, useEffect, useState} from 'react';
import {StyleSheet, TouchableOpacity, View} from 'react-native';
import {CameraType, FlashMode, RNCamera} from 'react-native-camera';
import {AnimatedCircularProgress} from 'react-native-circular-progress';
import CloseIcon from '../../assets/ionicons/close-outline.svg';
import {
  FlashButton,
  FlipButton,
  GalleryIcon,
  SaveButton,
  TaggSquareButton,
} from '../../components';
import {TAGG_PURPLE} from '../../constants';
import {MainStackParams} from '../../routes';
import {HeaderHeight, normalize, SCREEN_WIDTH} from '../../utils';
import {showGIFFailureAlert, takePicture, takeVideo} from '../../utils/camera';

type CameraScreenRouteProps = RouteProp<MainStackParams, 'CameraScreen'>;
export type CameraScreenNavigationProps = StackNavigationProp<
  MainStackParams,
  'CameraScreen'
>;
interface CameraScreenProps {
  route: CameraScreenRouteProps;
  navigation: CameraScreenNavigationProps;
}
const CameraScreen: React.FC<CameraScreenProps> = ({route, navigation}) => {
  const {screenType, selectedCategory} = route.params;
  const cameraRef = createRef<RNCamera>();
  const tabBarHeight = useBottomTabBarHeight();
  const [cameraType, setCameraType] = useState<keyof CameraType>('front');
  const [flashMode, setFlashMode] = useState<keyof FlashMode>('off');
  const [mediaFromGallery, setMediaFromGallery] = useState<string>('');
  const [mostRecentPhoto, setMostRecentPhoto] = useState<string>('');
  const [showSaveButton, setShowSaveButton] = useState<boolean>(false);
  const [isRecording, setIsRecording] = useState<boolean>(false);

  useFocusEffect(
    useCallback(() => {
      navigation.dangerouslyGetParent()?.setOptions({
        tabBarVisible: false,
      });
    }, [navigation]),
  );

  /*
   *  Chooses the last picture from gallery to display as the gallery button icon
   */
  useEffect(() => {
    CameraRoll.getPhotos({first: 1})
      .then((lastPhoto) => {
        if (lastPhoto.edges.length > 0) {
          const image = lastPhoto.edges[0].node.image;
          setMostRecentPhoto(image.uri);
        }
      })
      .catch((_err) =>
        console.log('Unable to fetch preview photo for gallery'),
      );
  }, [mediaFromGallery]);

  const navigateToCropper = (uri: string) => {
    navigation.navigate('ZoomInCropper', {
      screenType,
      media: {
        uri,
        isVideo: false,
      },
      selectedCategory,
    });
  };

  const navigateToCaptionScreen = (isVideo: boolean, uri: string) => {
    navigation.navigate('CaptionScreen', {
      screenType,
      media: {
        uri,
        isVideo,
      },
    });
  };

  /*
   * If picture is not taken yet, exists from camera screen to profile view
   * If picture is taken, exists from captured image's preview to camera
   * */
  const handleClose = () => {
    if (showSaveButton) {
      cameraRef.current?.resumePreview();
      setShowSaveButton(false);
      setMediaFromGallery('');
    } else {
      navigation.dangerouslyGetParent()?.setOptions({
        tabBarVisible: true,
      });
      navigation.goBack();
    }
  };

  return (
    <View style={styles.container}>
      <TouchableOpacity style={styles.closeButton} onPress={handleClose}>
        <CloseIcon height={25} width={25} color={'white'} />
      </TouchableOpacity>
      <FlashButton flashMode={flashMode} setFlashMode={setFlashMode} />
      <RNCamera
        ref={cameraRef}
        style={styles.camera}
        type={cameraType}
        flashMode={flashMode}
        onDoubleTap={() => {
          setCameraType(cameraType === 'front' ? 'back' : 'front');
        }}
      />
      <View style={[styles.bottomContainer, {bottom: tabBarHeight}]}>
        {showSaveButton ? (
          <SaveButton capturedImageURI={mediaFromGallery} />
        ) : (
          <FlipButton cameraType={cameraType} setCameraType={setCameraType} />
        )}
        <TouchableOpacity
          activeOpacity={1}
          onLongPress={() => {
            takeVideo(cameraRef, (vid) => {
              navigateToCaptionScreen(true, vid.uri);
            });
            setIsRecording(true);
          }}
          onPressOut={async () => {
            if (await cameraRef.current?.isRecording()) {
              cameraRef.current?.stopRecording();
              setIsRecording(false);
            }
          }}
          onPress={() => {
            takePicture(cameraRef, (pic) => {
              setShowSaveButton(true);
              setMediaFromGallery(pic.uri);
            });
          }}
          style={
            isRecording
              ? styles.captureButtonVideoContainer
              : styles.captureButtonContainer
          }>
          <View style={styles.captureButton} />
        </TouchableOpacity>
        {isRecording && (
          <AnimatedCircularProgress
            size={95}
            width={6}
            fill={100}
            rotation={0}
            duration={60000 + 1000} // an extra second for UI to load
            tintColor={TAGG_PURPLE}
            style={styles.bottomContainer}
            lineCap={'round'}
          />
        )}
        <View style={styles.bottomRightContainer}>
          {mediaFromGallery ? (
            <TaggSquareButton
              onPress={() => navigateToCaptionScreen(false, mediaFromGallery)}
              title={'Next'}
              buttonStyle={'large'}
              buttonColor={'blue'}
              labelColor={'white'}
              style={styles.nextButton}
              labelStyle={styles.nextButtonLabel}
            />
          ) : (
            <GalleryIcon
              mostRecentPhotoUri={mostRecentPhoto}
              callback={(media) => {
                const filename = media.filename;
                if (
                  filename &&
                  (filename.endsWith('gif') || filename.endsWith('GIF'))
                ) {
                  showGIFFailureAlert(() => navigateToCropper(media.path));
                } else {
                  // is this a video?
                  // if (media.duration !== null) {
                  //   navigateToCaptionScreen(true, media.path);
                  // } else {
                  //   navigateToCropper(media.path);
                  // }
                  navigateToCropper(media.path);
                }
              }}
            />
          )}
        </View>
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  camera: {
    flex: 1,
    justifyContent: 'space-between',
  },
  container: {
    flex: 1,
    flexDirection: 'column',
    backgroundColor: 'black',
  },
  captureButtonVideoContainer: {
    alignSelf: 'center',
    backgroundColor: 'transparent',
    borderRadius: 100,
    borderWidth: 15,
    borderColor: 'rgba(255,255,255,0.3)',
    width: 93,
    height: 93,
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'center',
  },
  captureButtonContainer: {
    alignSelf: 'center',
    backgroundColor: 'transparent',
    borderRadius: 100,
    borderWidth: 4,
    borderColor: '#fff',
    width: 93,
    height: 93,
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'center',
  },
  captureButton: {
    backgroundColor: '#fff',
    width: 68,
    height: 68,
    borderRadius: 74,
  },
  closeButton: {
    position: 'absolute',
    top: 0,
    paddingTop: HeaderHeight,
    zIndex: 1,
    marginLeft: '5%',
  },
  bottomContainer: {
    position: 'absolute',
    width: SCREEN_WIDTH,
    flexDirection: 'row',
    justifyContent: 'center',
  },
  bottomRightContainer: {
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'center',
    width: (SCREEN_WIDTH - 100) / 2,
  },
  nextButton: {
    zIndex: 1,
    width: normalize(100),
    height: normalize(37),
    borderRadius: 10,
  },
  nextButtonLabel: {
    fontWeight: '700',
    fontSize: normalize(15),
    lineHeight: normalize(17.8),
    letterSpacing: normalize(1.3),
    textAlign: 'center',
  },
});

export default CameraScreen;
