import React, { useRef, useCallback, useState, useEffect, useMemo } from "react";
import { Dimensions, Image, Platform, StatusBar, Text, TouchableOpacity, View, Animated, Alert, StyleSheet } from "react-native";
import Reanimated, {
    Extrapolate, interpolate, runOnJS, useAnimatedProps, useAnimatedReaction, useSharedValue,
} from 'react-native-reanimated';

import { customCamera, customStyles, deffontfamily, GetPageTheme, WP } from "../styles/Global";
import { useRoute } from '@react-navigation/native';
import { useCameraDevice, useCameraDevices, useFrameProcessor } from 'react-native-vision-camera';
import PropTypes from 'prop-types';
import { notify } from "./notify";
import { hasCameraPermission } from "./geolocation";
import { AntDesign, Entypo, MaterialCommunityIcons, MaterialIcons } from "./icons";
import { connect } from 'react-redux';
import { mapStateToProps, mapDispatchToProps } from '../reducers/contextProvider';
import { launchImageLibrary } from 'react-native-image-picker';
import Orientation from 'react-native-orientation-locker';
import { PORTRAIT } from "react-native-orientation-locker";
import moment from "moment";
import * as RNFS from 'react-native-fs';
import ViewShot, { CaptureOptions, captureRef } from "react-native-view-shot";
import { Gesture, PinchGestureHandler } from 'react-native-gesture-handler';
import CustomModal from "./CustomModal";
const { width, height } = Dimensions.get('window');
//import { Camera } from "react-native-vision-camera-v3-image-labeling";
import { Camera } from "react-native-vision-camera";
import { useNavigation } from '@react-navigation/native';
import { SafeAreaView } from "react-native-safe-area-context";
//useImageLabeler
const VC_OR = {
    "landscapeLeft": "landscapeLeft",
    "landscapeRight": "landscapeRight",
    "portraitUpsideDown": "portraitUpsideDown",
    "portrait": "portrait",
}

function CustomCamera(props) {
    const cameraRef = useRef(null);
    const route = useRoute();
    const navigation = useNavigation();
    const PageTheme = GetPageTheme(props.DarkTheme, route.name);
    const cameraStyle = customCamera(props.DarkMode, route.name);
    const customStyle = customStyles(props.DarkMode, route.name);
    const camera = useRef(null)
    const viewShotRef = useRef();
    const devices = useCameraDevices();
    const supportsCameraFlipping = useMemo(() => devices.back != null && devices.front != null, [devices.back, devices.front]);
    const dim = Dimensions.get("window");
    const [barcode, setBarcode] = React.useState({});
    const [qrCodeEnable, setQRCodeEnable] = useState(false);
    const orAnim = useRef(new Animated.Value(0)).current;
    const [showImage, setshowImage] = useState(false);
    const [imgurl, setimgurl] = useState('');
    const [temp_imgurl, setTemp_imgurl] = useState('');
    const [BottomText, setBottomText] = useState(props.BottomText || '');
    const [TopText, setTopText] = useState('');
    const [photoObj, setPhotoObj] = useState({});
    const [isActive, setisActive] = useState(false);
    const [isPhotoTaken, setIsPhotoTaken] = useState(false);
    const [isCameraActive, setIsCameraActive] = useState(false);
    const [activeFlashMode, setActiveFlashMode] = useState('off');

    const [orientation, setOrientation] = useState(PORTRAIT.toLowerCase());
    const [islandscape, setIslandscape] = useState(false);
    const [showCameraForScreen, setShowCameraForScreen] = useState(true);
    const [gridEnable, setGridEnable] = useState(false);
    const [showCapLandsImgAlert, setShowCapLandsImgAlert] = useState(false);
    const [count, setCount] = useState(0);
    const [ImageExtraSPace, setImageExtraSPace] = useState(1.06);
    const [cameraPosition, setCameraPosition] = useState((props.cameraType == 'front' ? 'front' : 'back'));
    const devices1 = useCameraDevice(props.cameraType == 'front' ? 'front' : 'back');
    const ReanimatedCamera = Reanimated.createAnimatedComponent(Camera)
    ////detect object
    const alertShown = useRef(false);
    const TARGET_LABELS = [
        'Mobile phone',
        'TV',
        'Television',
        'Tablet',
        'Laptop',
        'Computer',
        'Musical instrument'
    ];

    const onDataReceived = useCallback((data) => {
        // console.log("data_new", data)
        // if (alertShown.current) return;

        // const filtered = data.filter(item =>
        //     TARGET_LABELS.includes(item.label)
        // );
        // if (filtered.length > 0) {
        //     console.log("filtered_new", filtered)
        //     alertShown.current = true;
        //     Alert.alert(
        //         '⚠️ Warning!',
        //         'Fake image detected!',
        //         [{
        //             text: 'OK', onPress: () => {
        //                 console.log("ddlfkdff")
        //                 navigation.goBack();
        //             }
        //         }]
        //     );
        // }
    }, []);

    Reanimated.addWhitelistedNativeProps({
        zoom: true,
    })
    const zoom = useSharedValue(0)
    zoom.value = 0
    // const minZoom = device?.minZoom ?? 1;
    const minZoom = devices1?.minZoom ?? 1;
    const maxZoom = Math.min(devices1?.maxZoom ?? 1, 20);
    const onZoomPress = useCallback(() => {
        // setCount(count+1)
        zoom.value = withSpring(count)
    }, [count])
    const SCALE_FULL_ZOOM = 3;
    // const zoom = useSharedValue(1);
    const startZoom = useSharedValue(1);
    const onPinchGesture = Gesture.Pinch()
        .onBegin(() => {
            startZoom.value = zoom.value;
        })
        .onUpdate((event) => {
            // Map pinch scale to linear zoom
            const scale = interpolate(
                event.scale,
                [1 - 1 / SCALE_FULL_ZOOM, 1, SCALE_FULL_ZOOM],
                [-1, 0, 1],
                Extrapolate.CLAMP
            );
            zoom.value = interpolate(
                scale,
                [-1, 0, 1],
                [minZoom, startZoom.value, maxZoom],
                Extrapolate.CLAMP
            );
        });

    const animatedProps = useAnimatedProps(
        () => ({ zoom: zoom.value }),
        [zoom]
    )

    useEffect(() => {
        let showGrid = props.gridEnable != null ? (props.gridEnable) : false;
        setGridEnable(showGrid);
    }, [props.gridEnable])

    useEffect(() => {
        let showQRCam = props.QRCodeEnable != null ? (props.QRCodeEnable) : false;
        setQRCodeEnable(showQRCam);
    }, [props.QRCodeEnable])

    useEffect(() => {
        console.log('CameraGallery in camera :', props.CameraGallery, 'for screen:', props.enableGallerForScreen);
        let showScreenCam = props.enableGallerForScreen != null ? (props.enableGallerForScreen) : true;
        setShowCameraForScreen(showScreenCam);
        hasCameraPermission();
        Orientation.addDeviceOrientationListener((orientation) => {
            let or = orientation.toLowerCase();
            if (or == 'unknown') or = 'portrait';
            let isLS = (or == 'landscape-left' || or == 'landscape-right' || or == 'landscape');
            let or_VC = or == 'landscape-left' ? VC_OR.landscapeRight : (or == 'landscape-right' ? VC_OR.landscapeLeft : (or == 'portrait-upside-down' ? VC_OR.portraitUpsideDown : VC_OR.portrait));
            setOrientation(or_VC);
            setIslandscape(isLS);
            Animated.timing(orAnim, {
                toValue: isLS ? 1 : 0,
                duration: 400,
                useNativeDriver: false,
            }).start();

            console.log("onchange:", orientation, or_VC);
        });

        return () => {
            Orientation.removeOrientationListener((orientation) => { console.log("or listener removed") });
            Orientation.removeAllListeners();
        }

    }, []);

    useEffect(() => {
        console.log('showCamera changed:', props.showCamera);
        alertShown.current = false;
        if (props.showCamera == true) {
            showCamera();
        }
        else {
            hideCamera();
        }
    }, [props.showCamera]);

    function showCamera() {
        console.log('showCamera customcamera');
        if (props.cameraType != 'front') {
            setShowCapLandsImgAlert(true);
            setTimeout(() => {
                setShowCapLandsImgAlert(false);
            }, 1500);
        }
        setIsCameraActive(true);
        setisActive(true);
    }

    async function hideCamera(type = '') {
        setIsCameraActive(false);
        setisActive(false);
        setimgurl('');
        setIsPhotoTaken(false);
        setshowImage(true);
        console.log("isCameraScreen", props.isCameraScreen, type)
        if (props.isCameraScreen != null && props.isCameraScreen == true) {
            // Don't call onHideCamera if it is a camera screen
            if (type == 'cancel') {
                props.onHideCamera();
            }
        }
        else {
            if (props.onHideCamera != null && typeof props.onHideCamera == 'function') {
                props.onHideCamera();
            }
        }
    }

    function closeCamera() {
        setIsCameraActive(false);
    }
    const onFlipCameraPressed = useCallback(() => {
        setCameraPosition((p) => (p === 'back' ? 'front' : 'back'));
    }, []);

    async function takePhoto() {
        console.log("Take foto")
        if (camera.current != null && typeof camera.current === 'object') {
            const photo = await camera.current.takePhoto({
                flash: activeFlashMode,
            })
            // console.log("taken photo params:",photo)
            if (photo != null) {
                let path = 'file://' + photo.path;
                let picture_clicked_time = moment().format('DD-MM-YYYY HH:mm:ss');
                console.log(path);
                // required larger height of image for landscape image 
                let ExtraSpace = 1.1; // portrait image  def 
                if (photo.width > photo.height) {
                    // landscape image 
                    ExtraSpace = 1.2
                }

                console.log("takephhoto:w x h", photo.width, photo.height, photo);
                let obj = { uri: path, original_path: photo.path, width: parseInt(photo.width), height: parseInt(photo.height), ExtendedHeight: parseInt(photo.height * ExtraSpace), or_Mode: orientation };
                setImageExtraSPace(ExtraSpace);
                setPhotoObj(obj);
                setTemp_imgurl(path)
                let bText = props.BottomText + " | Date: " + picture_clicked_time;
                setBottomText(bText);
                setTopText(picture_clicked_time);
                setIsPhotoTaken(true);
            }
            else {
                notify('Something went wrong! Cannot take picture.');
                setisActive(false);
            }
        }
        else {
            notify('Camera not found!.');
            setisActive(false);
        }

        closeCamera();
    }

    async function onRetake() {
        await RNFS.unlink(temp_imgurl);
        // setTemp_imgurl('');
        setIsPhotoTaken(false);
        setshowImage(false);
        setIsCameraActive(true);
        setisActive(true);
    }
    async function onCameraImgOk() {
        zoom.value = 0
        let obj = photoObj;
        obj.viewShotRef = viewShotRef;
        setPhotoObj(obj);
        setisActive(false);
        setIsPhotoTaken(false);
        setshowImage(true);
        if (props.onImageCaptured != null && typeof props.onImageCaptured == 'function') {
            props.onImageCaptured(obj);
        }

        hideCamera();
    }

    async function onQRScanned(qrData) {
        console.log("qrData:", qrData.data);
        setisActive(false);
        if (props.onImageCaptured != null && typeof props.onImageCaptured == 'function') {
            let QR_withValidChars = qrData.data != null && qrData.data != '' ? qrData.data.replace(/["']/g, '') : '';
            props.onImageCaptured(QR_withValidChars);
        }
        hideCamera();
    }

    function flashOnOff(type = '') {
        console.log('setflashmode:', type);
        if (type != '' && type != null) {
            setActiveFlashMode(type);
            if (type == 'on') {

            }
            else if (type == 'off') {

            }
            else if (type == 'auto') {

            }
        }
    }

    function pickGalleryImage(img) {
        console.log('pickGalleryImage:', img, typeof img.assets);
        if (img != null && img.assets != null && typeof img.assets == 'object' && img.assets.length > 0 && img.assets[0].uri != null) {
            let photo = img.assets[0];
            let path = photo.uri;
            console.log(path);
            let times = photo.timestamp != null && photo.timestamp != '' ? photo.timestamp : new Date();
            let obj = { uri: path, width: photo.width, height: photo.height, 'fromGallery': true, 'datetime': times };
            setPhotoObj(obj);
            setTemp_imgurl(path)
            let picture_clicked_time = moment().format('DD-MM-YYYY HH:mm:ss');
            let bText = props.BottomText + " | " + picture_clicked_time;

            setTopText(picture_clicked_time);
            setBottomText(bText);
            setIsPhotoTaken(true);
        }
        else {
            notify('Something went wrong! Cannot take picture.');
            setisActive(false);
        }
    }

    function getImageFromGallery() {
        launchImageLibrary({ mediaType: 'photo', selectionLimit: 1, includeExtra: true, cameraType: 'front' }, pickGalleryImage)
    }

    function _renderCaptureBtn() {
        return (
            <>
                <TouchableOpacity style={cameraStyle.customCamera_capbtn} onPress={() => { takePhoto(); }}>
                    <View style={cameraStyle.customCamera_capbtn_Outer}><View style={cameraStyle.customCamera_capbtn_Inner}></View></View>
                </TouchableOpacity>
            </>
        )
    }

    function _renderGalleryBtn() {
        return (
            <TouchableOpacity style={cameraStyle.customCamera_Gallerybtn} onPress={() => { getImageFromGallery() }}>
                <View style={cameraStyle.customCamera_Gallerybtn_Outer}>
                    <View style={cameraStyle.customCamera_Gallerybtn_Inner}>
                        <Entypo name='images' size={32} color={PageTheme.$text_color} style={cameraStyle.customCamera_Gallerybtn_Icon} />
                    </View>
                </View>
            </TouchableOpacity>
        )
    }

    function _renderBottomControls() {
        return (
            <View style={(cameraStyle.customCamera_bottomBar)}>
                {_renderCaptureBtn()}
                {props.CameraGallery == true && showCameraForScreen == true &&
                    _renderGalleryBtn()
                }
            </View>
        )
    }
    function _renderOrientationIcon() {
        let deg = 0;
        if (orAnim != null) {
            deg = orAnim.interpolate({
                inputRange: [0, 1],
                outputRange: ['0deg', '90deg'],
            });
        }
        return (
            <Animated.View style={[cameraStyle.or_icon, { transform: [{ rotate: deg }], }]}>
                <AntDesign name='mobile1' color={'#ffffffdb'} size={18} />
            </Animated.View>
        )
    }

    function _renderCancelBtn() {
        return (
            <TouchableOpacity style={cameraStyle.imgControls_btnCon} onPress={() => { hideCamera('cancel') }}>
                <View style={cameraStyle.imgControls_btn}>
                    <MaterialCommunityIcons name='cancel' color={'#fff'} size={18} />
                    <Text style={[cameraStyle.imgControls_btnText, cameraStyle.icbtTop]}>Cancel</Text>
                </View>
            </TouchableOpacity>
        )
    }

    function _renderRetakeBtn() {
        return (
            <TouchableOpacity style={cameraStyle.imgControls_centerBtn} onPress={() => { onRetake() }}>
                <View style={cameraStyle.imgControls_btn}>
                    <View style={cameraStyle.imgControls_retakeBtn}>
                        <MaterialCommunityIcons name='camera-retake' color={'#000'} size={30} />
                    </View>
                    <Text style={[cameraStyle.imgControls_btnText, cameraStyle.icbtTop]}>Retake</Text>
                </View>
            </TouchableOpacity>
        )
    }



    function _renderSaveImgBtn() {
        return (
            <TouchableOpacity style={cameraStyle.imgControls_btnCon} onPress={() => { onCameraImgOk() }}>
                <View style={cameraStyle.imgControls_btn}>
                    <MaterialCommunityIcons name='check' color={'#fff'} size={18} />
                    <Text style={[cameraStyle.imgControls_btnText, cameraStyle.icbtTop]}>Ok</Text>
                </View>
            </TouchableOpacity>
        )
    }



    function _renderImageControls() {
        return (
            <SafeAreaView style={cameraStyle.customCamera_bottomBar2}>
                <View style={cameraStyle.imgControls}>
                    {_renderCancelBtn()}
                    {_renderRetakeBtn()}
                    {_renderSaveImgBtn()}
                </View>
            </SafeAreaView>
        )
    }

    function _renderFlashBtn(type = 'on') {
        return (
            <TouchableOpacity style={cameraStyle.flashBtn} onPress={() => { flashOnOff(type) }}>
                {type == 'on' && <MaterialCommunityIcons name='flash' color={(activeFlashMode == 'on' ? '#ffe600' : '#fff')} size={24} />}
                {type == 'off' && <MaterialCommunityIcons name='flash-off' color={(activeFlashMode == 'off' ? '#ffe600' : '#fff')} size={24} />}
                {type == 'auto' && <MaterialCommunityIcons name='flash-auto' color={(activeFlashMode == 'auto' ? '#ffe600' : '#fff')} size={24} />}
            </TouchableOpacity>
        )
    }

    function _renderCameraSwapMode() {
        return (
            <TouchableOpacity style={cameraStyle.flashBtn} onPress={() => { onFlipCameraPressed() }}>
                {cameraPosition == 'front' && <MaterialIcons name='flip-camera-ios' color={'#ffe600'} size={24} />}
                {cameraPosition == 'back' && <MaterialIcons name='flip-camera-android' color={'#fff'} size={24} />}
            </TouchableOpacity>
        )
    }

    function _renderTopControls() {
        return (
            <View style={cameraStyle.topControls}>
                <View style={cameraStyle.topControlsInner}>
                    {_renderFlashBtn('on')}
                    {_renderFlashBtn('off')}
                </View>
            </View>
        )
    }

    function _renderSideControls() {

        let enableCameraFlip = props.enableCameraFlip != null ? (props.enableCameraFlip) : false;
        return (
            <View style={(cameraStyle.sideControls)}>
                <View style={cameraStyle.sideControlsInner}>
                    {_renderFlashBtn('on')}
                    {_renderFlashBtn('off')}
                    {supportsCameraFlipping && enableCameraFlip == true &&
                        _renderCameraSwapMode()
                    }
                </View>
            </View>
        )
    }
    const cameraAnimatedProps = useAnimatedProps(() => {
        const z = Math.max(Math.min(zoom.value, maxZoom), minZoom);
        return {
            zoom: z,
        };
    }, [maxZoom, minZoom, zoom]);



    const cameraView = () => {
        // return (
        //     <QRCodeScanner
        //         onRead={onQRScanned}
        //         showMarker={true}
        //         cameraStyle={[cameraStyle.customCamera, (islandscape || props.cameraType == 'front' ? cameraStyle.customCameraLS : {})]} //(props.cameraType!='front'?{}:cameraStyle.customCameraTop)
        //     />
        // )
    }

    function _render_AutoAlertModal() {
        return (
            <CustomModal
                style={customStyle.storelVisitM_Style}
                title={"Please click image in landscape mode!"}
                titleStyle={customStyle.storelVisitM_titleStyle}
                showModal={showCapLandsImgAlert}
            >
                <View></View>
            </CustomModal>
        )
    }

    function _renderSCreenSHotView() {
        let is_photo_mode_LS = (photoObj.or_Mode == VC_OR.landscapeLeft || photoObj.or_Mode == VC_OR.landscapeRight)
        let imgSIze = (photoObj.or_Mode != null && photoObj.or_Mode != '' ? (is_photo_mode_LS ? { width: '100%' } : { height: '100%' }) : {});
        let vieshotStyle = {};
        let itemW = photoObj.width, itemH = photoObj.height;

        let hR = (itemH / itemW) * 100;
        let screenWidth = WP('100%');
        let ht = screenWidth * (hR / 100);
        vieshotStyle = { width: '100%', height: ht };



        return (
            <View style={[cameraStyle.customCamera_Wrap, { justifyContent: 'center', alignItems: 'center' }]}>
                {temp_imgurl != null && temp_imgurl != '' &&
                    <View style={[vieshotStyle]}   >
                        {/*  (props.cameraType == 'front' && Platform.OS=='ios' ? { transform: [{ scaleX: -1 }] } : {}) */}
                        <Image source={{ uri: temp_imgurl }} style={[imgSIze, cameraStyle.cameraImgCaptured]} resizeMode={'contain'} />
                    </View>}
                {_renderImageControls()}
            </View>
        )
    }

    return (
        <View style={[cameraStyle.CameraWrapper, (props.showCamera == true && isActive == true ? {} : cameraStyle.CameraWrapperHide)]} >
            {temp_imgurl != null && temp_imgurl != '' &&
                <View style={{ position: 'absolute', left: 0, top: 0, opacity: 0 }}>
                    <ViewShot ref={viewShotRef} options={{ format: "jpg", quality: 1.0 }} >
                        <View collapsable={false} style={{ width: photoObj.width, height: parseInt(photoObj.height * ImageExtraSPace), backgroundColor: '#fff' }} >
                            <Image source={{ uri: temp_imgurl }} style={[{ width: photoObj.width, height: photoObj.height }, cameraStyle.cameraImgCaptured, (props.cameraType == 'front' ? { transform: [{ scaleX: -1 }] } : {})]} />
                            {TopText != null && TopText != '' && <Text style={{ position: 'absolute', left: 10, top: 10, fontFamily: deffontfamily, color: 'red', fontSize: parseInt(photoObj.width * 0.04) }} >{TopText}</Text>}
                            {BottomText != null && BottomText != '' && <Text style={{ position: 'absolute', left: 0, paddingHorizontal: 5, top: (photoObj.height + 5), fontFamily: deffontfamily, color: 'red', fontSize: parseInt(photoObj.width * 0.03), flexWrap: 'wrap' }} >{BottomText}</Text>}
                        </View>
                    </ViewShot>
                </View>
            }
            {props.showCamera == true && isActive == true &&
                <View style={cameraStyle.scrollMain}>
                    <StatusBar translucent={true} hidden={true} />
                    {
                        Platform.OS == 'ios' &&
                        <View style={cameraStyle.IOS_StatusBar}>
                        </View>
                    }
                    {devices1 != null && isActive &&
                        <View style={[cameraStyle.customCamera_Wrap]} ref={cameraRef}>
                            {qrCodeEnable == true ? cameraView() :
                                <>
                                    {_render_AutoAlertModal()}
                                    <PinchGestureHandler onGestureEvent={onPinchGesture} enabled={isActive}>
                                        <Reanimated.View style={StyleSheet.absoluteFill}>
                                            {/* <ReanimatedCamera
                                                ref={camera}
                                                style={[cameraStyle.customCamera, { width: '100%', height: '100%' }, (islandscape || props.cameraType == 'front' ? cameraStyle.customCameraLS : {})]} //(props.cameraType!='front'?{}:cameraStyle.customCameraTop)
                                                device={devices1}
                                                isActive={isCameraActive}
                                                photo={true}
                                                focusable={true}
                                                torch={activeFlashMode == 'on' ? FlashModeAction : 'off'}
                                                orientation={orientation}
                                                enableZoomGesture={true}
                                                animatedProps={cameraAnimatedProps}
                                                frameProcessor={frameProcessor}
                                                frameProcessorFps={2}
                                            // fps={60}
                                            // zoom={zoom.value}
                                            /> */}

                                            <ReanimatedCamera
                                                key={isCameraActive ? 'active' : 'inactive'}
                                                ref={camera}
                                                style={[cameraStyle.customCamera, { width: '100%', height: '100%' }, (islandscape || props.cameraType == 'front' ? cameraStyle.customCameraLS : {})]} //(props.cameraType!='front'?{}:cameraStyle.customCameraTop)
                                                device={devices1}
                                                isActive={isCameraActive}
                                                photo={true}
                                                focusable={true}
                                                torch={activeFlashMode === 'on' ? 'on' : 'off'}
                                                orientation={orientation}
                                                enableZoomGesture={true}
                                                animatedProps={cameraAnimatedProps}
                                                //options={{minConfidence: 0.6}}
                                                //callback={onDataReceived}
                                            />
                                        </Reanimated.View>
                                    </PinchGestureHandler>
                                    {_renderOrientationIcon()}
                                    {_renderBottomControls()}
                                    {props.cameraType != 'front' && _renderSideControls()}
                                </>
                            }
                        </View>
                    }
                    {devices1 != null && (temp_imgurl != null && temp_imgurl != '') && isPhotoTaken &&
                        _renderSCreenSHotView()
                    }
                </View>
            }
        </View>
    )

};

export default connect(mapStateToProps, mapDispatchToProps)(CustomCamera);

CustomCamera.propTypes = {
    cameraType: PropTypes.oneOf(['front', 'back']),
    showCamera: PropTypes.bool,
    onImageCaptured: PropTypes.func,
    onHideCamera: PropTypes.func,


};
