import { useFocusEffect } from "@react-navigation/native";
import { Camera } from "expo-camera";
import * as FileSystem from "expo-file-system";
import React, { useEffect, useRef, useState } from "react";
import { Text, View } from "react-native";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import {
  selectCurrentCameraJob,
  selectCurrentCameraJobId,
} from "../../redux/app/app.selectors";
import { addPhoto } from "../../redux/photos/photos.actions";
import CameraControls from "../camera-controls/camera-controls.component";
import CameraSelectJob from "../camera-select-job/camera-select-job.component";

const mapStateToProps = createStructuredSelector({
  cameraJobId: selectCurrentCameraJobId,
  cameraJob: selectCurrentCameraJob,
});
const mapDispatchToProps = (dispatch) => ({
  addPhoto: (photo) => dispatch(addPhoto(photo)),
});

export function ScreenCamera({ cameraJobId, addPhoto }) {
  const [hasPermission, setHasPermission] = useState(null);
  const [state, setState] = useState({
    flashMode: Camera.Constants.FlashMode.off,
    capturing: null,
    cameraType: Camera.Constants.Type.back,
    tabHasFocus: null,
  });
  const cameraRef = useRef(null);

  useFocusEffect(
    React.useCallback(() => {
      // Do something when the screen is focused
      setState({ ...state, tabHasFocus: true });
      return () => {
        // Do something when the screen is unfocused
        // Useful for cleanup functions
        setState({ ...state, tabHasFocus: false });
      };
    }, [])
  );

  useEffect(() => {
    (async () => {
      const { status } = await Camera.requestPermissionsAsync();
      setHasPermission(status === "granted");
    })();
  }, []);

  const setFlashMode = (flashMode) => setState({ ...state, flashMode });
  const setCameraType = (cameraType) => setState({ ...state, cameraType });
  const handleCaptureIn = () => setState({ ...state, capturing: true });

  const handleCaptureOut = () => {
    if (state.capturing) cameraRef.current.stopRecording();
  };

  const handleShortCapture = async () => {
    if (cameraRef.current) {
      const options = {
        quality: 0.8,
        //base64: true,
        skipProcessing: true,
      };

      let photo = await cameraRef.current.takePictureAsync(options);
      const filename = photo.uri.substring(photo.uri.lastIndexOf("/") + 1);
      const newUri = FileSystem.documentDirectory + "photos/" + filename;

      await FileSystem.moveAsync({
        from: photo.uri,
        to: newUri,
      });
      setState({ ...state, capturing: false });
      addPhoto({
        ...photo,
        id: filename,
        uri: newUri,
        jobId: cameraJobId,
        video: false,
      });
    }
  };

  const handleLongCapture = async () => {
    console.log("Taking a video!");
    if (cameraRef.current) {
      let video = await cameraRef.current.recordAsync();

      const filename = video.uri.substring(video.uri.lastIndexOf("/") + 1);
      const newUri = FileSystem.documentDirectory + "photos/" + filename;

      await FileSystem.moveAsync({
        from: video.uri,
        to: newUri,
      });
      setState({ ...state, capturing: false });
      console.log("Adding Photo", {
        ...video,
        id: filename,
        uri: newUri,
        jobId: cameraJobId,
        video: true,
      });
      addPhoto({
        ...video,
        id: filename,
        uri: newUri,
        jobId: cameraJobId,
        video: true,
      });
    }
  };

  if (hasPermission === null || !state.tabHasFocus) {
    return <View />;
  }

  if (hasPermission === false) {
    return <Text>No access to camera. Please ensure that you allow it.</Text>;
  }

  const { flashMode, cameraType, capturing } = state;

  return (
    <Camera
      style={{ flex: 1, display: "flex" }}
      type={state.cameraType}
      ref={cameraRef}
      ratio={"16:9"}
    >
      <View
        style={{
          flex: 1,
        }}
      >
        <CameraSelectJob />

        <CameraControls
          capturing={capturing}
          flashMode={flashMode}
          cameraType={cameraType}
          setFlashMode={setFlashMode}
          setCameraType={setCameraType}
          onCaptureIn={handleCaptureIn}
          onCaptureOut={handleCaptureOut}
          onLongCapture={handleLongCapture}
          onShortCapture={handleShortCapture}
        />
      </View>
    </Camera>
  );
}
export default connect(mapStateToProps, mapDispatchToProps)(ScreenCamera);
