/* Copyright (C) Click & Push Accessibility, Inc - All Rights Reserved
 * Unauthorized copying of this file, via any medium is strictly prohibited
 * Proprietary and confidential
 * Written and maintained by the Click & Push Development team 
 * <dev@clicknpush.ca>, January 2022
 */

import { FontAwesome } from "@expo/vector-icons";
import { ImageInfo } from "expo-image-picker/build/ImagePicker.types";
import React, { memo, useEffect, useState, useRef } from "react";
import { ActivityIndicator, Dimensions, Image, Platform, SafeAreaView, Text, TextInput, TouchableOpacity, View, ImageSourcePropType, Share, KeyboardEventName, Keyboard, StyleSheet, KeyboardAvoidingView, Alert } from 'react-native';
import { ScrollView } from "react-native-gesture-handler";
import Modal from 'react-native-modal';
import Picker from 'react-native-picker-select';
import { Landmark, LMPhoto, useAddLandmark } from "../../../data/landmarks";
import { colors, lmTypes as allLmTypes, lmTypesIndoor } from "../../../utils/GlobalUtils";
import { IconButton, SecondaryButton } from "../../Buttons";
import { PhotoPicker } from "../../PhotoPicker";
import TouchOpaq from "./LandmarkDetailsPanel/TouchOpaq";
import { Svg, Rect, Image as ImageSVG, Circle } from 'react-native-svg'
import ReactDOMServer from 'react-dom/server'; //npm i --save-dev @types/react-dom


import IndoorFloor from "../IndoorFloor";
import ViewShot, { captureRef, captureScreen } from "react-native-view-shot";

import { useNavigationState } from "@react-navigation/native"
import LandmarkTypePicker from "../../LandmarkTypePicker";


/**
 * Props for the {@link AddLandmarkPanel} component.
 */
export interface AddLandmarkProps {
    /**
     * Whether the landmark is being added at the current users location
     */
    landmarkAtCurrentLocation?: boolean;
    /**
     * The {@link landmark} object to be added.
     */
    newLandmark?: Landmark;
    /**
     * The state updater for the new {@link landmark} to be added.
     */
    setNewLandmark: (landmark: Landmark) => void;
    /**
     * A call back that toggles the visibility state of the {@link AddLandmarkPanel} modal. Passed down from {@link AddLandmarkPanel}.
     */
    setVisible: (state: boolean) => void;
    visible: boolean;
}

/**
 * Component that renders a form for adding a new {@link Landmark}. Contained within a [react-native-modal]{@link https://github.com/react-native-modal/react-native-modal}.
 * @component
 * @category Map
 */
const AddLandmarkPanel: React.FC<AddLandmarkProps> = ({ newLandmark, setNewLandmark, setVisible, visible }) => {
    const [photos, setPhotos] = useState<LMPhoto[]>([])
    const [photoSourceMenuOpened, togglePhotoSourceMenu] = useState<boolean>(false)
    const [keyboardOpened, setKeyboardOpened] = useState<boolean>(false);

    const addLandmarkMutation = useAddLandmark()

    const navigationState = useNavigationState(state => state)
    const [currentRoute, setCurrentRoute] = useState<string>()
    useEffect(() => {
        const currentRouteIndex = navigationState?.routes[0]?.state?.index
        const currentRouteName = navigationState?.routes[0]?.state?.routeNames[currentRouteIndex]
        setCurrentRoute(currentRouteName)
    }, [navigationState])

    
    useEffect(() => {
        let eventString = Platform.OS == "android" ? 'keyboardDidShow' : Platform.OS == "ios" ? 'keyboardWillShow' : null;
        if (eventString) {
            const validEventString: KeyboardEventName = eventString as KeyboardEventName;

            const keyboardDidShowListener = Keyboard.addListener(
                validEventString,
                () => {
                    setKeyboardOpened(true); // or some other action
                }
            );
            const keyboardDidHideListener = Keyboard.addListener(
                validEventString,
                () => {
                    setKeyboardOpened(false); // or some other action
                }
            );

            return () => {
                keyboardDidHideListener.remove();
                keyboardDidShowListener.remove();
            };
        }
    }, []);

    /**
     * Returns a height for the modal depending on if an image is maximzed, if the keyboard is opened, and if the current landmark has photos associated with it
     */
    const determineModalHeight = () => {
        if (keyboardOpened) {
            return Dimensions.get("window").height * .45
        }
        else if (photos?.length > 0)
            return Dimensions.get("window").height * .9
        else
            return Dimensions.get("window").height * .6
    }
    const capture: any = useRef();

    const imgWidth = 346
    const imgHeight = 448
    const imageDim = 25
    
    let lmTypes = allLmTypes
    if(currentRoute=="Indoor") {
        lmTypes = lmTypesIndoor
    }

    useEffect(() => {
        /**
         * Resets the {@link addLandmarkAsync} mutation on successful add.
         * Embedded in a useEffect that listens to the {@link addLandmarkStatus} value from the {@link useLandmarks} hook.
         * @memberOf AddLandmark
         */
        const resetAddMutationOnSuccess = () => {
            if (addLandmarkMutation.isSuccess) {
                addLandmarkMutation.reset()
            }
        }
        resetAddMutationOnSuccess();
    }, [addLandmarkMutation.status]);

    useEffect(() => {
        addLandmarkMutation.reset()
    }, [visible]);

    /**
     * Calls {@link addLandmarkAsync} from {@link useLandmarks} to initate the process of adding a landmark, then closes the modal.
     */
    const submit = async () => {
        if (typeof newLandmark.floor === 'number') {
            try {
                const uri = await captureRef(capture, {
                    format: "jpg",
                    quality: 1,
                    result: 'base64'
                })

                await addLandmarkMutation.mutateAsync({ landmarkValue: newLandmark, photos: photos, indoorLmLocImg: uri }); // pass it in here


            } catch (error) {
                console.error("Oops, snapshot failed", error)
            }
        }
        else {
            await addLandmarkMutation.mutateAsync({ landmarkValue: newLandmark, photos: photos })
        }


        // create svg content here, then pass it to addLandmarkAsync as the value of indoorLmLocImg
        // if (typeof newLandmark.floor === 'number') {
        //     let rectangle = serialize()
        //     await addLandmarkAsync({ landmarkValue: newLandmark, photos: photos, indoorLmLocImg: rectangle }); // pass it in here
        // }
        // else {
        //     await addLandmarkAsync({ landmarkValue: newLandmark, photos: photos });
        // }

        close()
    }

    /**
     * Closes the modal.
     */
    const close = () => {
        setPhotos([])
        setVisible(false)
        togglePhotoSourceMenu(false)
        setNewLandmark({})
    }

    const addPhoto = (result: ImageInfo) => {
        togglePhotoSourceMenu(false)
        const photo: LMPhoto = { id: '', image_b64: 'data:image/png;base64,' + result.base64, height: result.height, width: result.width, landmark: '' }
        setPhotos([...photos, photo])
    }

    const deletePhoto = (index: number) => {
        setPhotos(photos.filter((photo, i) => i != index))
    }

    return (
        <Modal
            useNativeDriver={true}
            useNativeDriverForBackdrop={true}
            testID="addLMModal"
            avoidKeyboard={photos?.length > 0}
            onBackdropPress={close}
            style={{ flex: 0, justifyContent: "flex-end", height: '100%', margin: 0 }}
            isVisible={visible} >

            <KeyboardAvoidingView
                behavior={Platform.OS === "ios" ? "padding" : "height"}
                enabled={photos?.length > 0}
            >
                <SafeAreaView style={{ backgroundColor: colors.red, height: determineModalHeight(), }}>
                    {addLandmarkMutation.isIdle ?
                        <>
                            <View style={{
                                justifyContent: 'space-between',
                                alignItems: 'center',
                                flexDirection: "row",
                                marginBottom: 15,
                                borderBottomWidth: 1,
                                borderBottomColor: 'white',
                                paddingHorizontal: 20,
                                paddingVertical: 10,
                            }}
                            onTouchStart={() => Keyboard.dismiss()}
                            >
                                <Text style={{ color: 'white', fontSize: 15 }}>Add landmark here?</Text>
                                <TouchOpaq
                                    func={close}
                                    name={"close"}
                                    size={25}
                                    col={"white"}
                                />

                            </View>
                            <ScrollView>
                                <View style={{ paddingHorizontal: 20, paddingBottom: 20 }}>
                                    <TextInput
                                        returnKeyType="done"
                                        blurOnSubmit={true}
                                        multiline={true}
                                        style={{ backgroundColor: 'white', textAlignVertical: 'top', paddingHorizontal: 10, paddingTop: 10, paddingBottom: 10, marginBottom: 20, height: 150 }}
                                        placeholder="Description"
                                        onChangeText={value => setNewLandmark({ ...newLandmark, description: value })}>
                                        {newLandmark?.description}
                                    </TextInput>
                                    <View style={{ flexDirection: 'row' }}>
                                        <LandmarkTypePicker 
                                            placeholder={{ label: "Select a landmark type...", value: 0 }}
                                            value={newLandmark?.landmark_type}
                                            onValueChange={(value) => {
                                                if (value) {
                                                    setNewLandmark({ ...newLandmark, landmark_type: value, title: lmTypes[value].label })
                                                }
                                                else {
                                                    setNewLandmark({ ...newLandmark, landmark_type: undefined, title: 'no title' })
                                                }
                                            }}
                                            items={Object.keys(lmTypes)?.map(icon => {
                                                return (
                                                    { label: lmTypes[parseInt(icon)]?.label.toUpperCase(), value: icon, key: icon }
                                                )
                                            })}/>

                                        {newLandmark?.landmark_type ? <Image style={{ marginLeft: 20 }} source={lmTypes[newLandmark.landmark_type].image} />
                                            : null}
                                    </View>
                                </View>
                                {newLandmark?.landmark_type ?
                                    <View style={{ justifyContent: 'flex-end', flexDirection: 'row', paddingHorizontal: 20, marginTop: 5 }}>
                                        {newLandmark.description && newLandmark.title ?
                                            <View style={{ flexDirection: 'row' }}>
                                                <TouchableOpacity onPress={async () => await submit()}><Text style={{ color: 'white', marginRight: 25 }}>Add</Text></TouchableOpacity>
                                                <TouchableOpacity onPress={close}><Text style={{ color: 'white', marginRight: 25 }}>Cancel</Text></TouchableOpacity>
                                                {photos.length == 0 ? <TouchableOpacity onPress={() => togglePhotoSourceMenu(true)}><Text style={{ color: 'white' }}>Include photos</Text></TouchableOpacity> : null}
                                            </View> : null}
                                    </View> : null}
                                {photos?.length > 0 && !keyboardOpened ?
                                    <View>
                                        <ScrollView style={{ borderTopWidth: 1, borderColor: 'lightgray', paddingTop: 20, marginHorizontal: 20, flexDirection: 'row', marginBottom: 5, marginTop: 30 }} horizontal={true}>
                                            {photos.map((photo, i) => {
                                                return (
                                                    <View key={i} style={{ marginHorizontal: 1, padding: 15 }}>
                                                        <IconButton style={{ position: 'absolute', top: 0, right: 0, zIndex: 10, }} icon="times-circle" color="lightgray" size={20} onPress={() => deletePhoto(i)} />
                                                        <Image style={{ borderWidth: 1, alignSelf: 'center', height: 200, width: 200 * photo.width / photo.height }} source={{ uri: photo.image_b64 }} />
                                                    </View>
                                                )
                                            })}
                                            {photos.length < 5 ? <IconButton style={{ alignSelf: 'center', padding: 10, opacity: .5, marginLeft: 10 }} color='white' size={30} icon="plus" onPress={() => togglePhotoSourceMenu(true)} /> : null}
                                        </ScrollView>
                                    </View> : null}
                            </ScrollView>
                        </> :
                        <View style={{ height: '100%', justifyContent: "space-evenly", alignItems: "center" }}>
                            <Text style={{ color: 'white', fontSize: 20 }}>{
                                addLandmarkMutation.isLoading ? 'Uploading landmark...' :
                                    addLandmarkMutation.isError ? 'Something went wrong when trying to upload the landmark.' : null}
                            </Text>
                            {
                                addLandmarkMutation.isLoading ? <ActivityIndicator color='white' size="large" /> :
                                    addLandmarkMutation.isError ? <SecondaryButton text="Okay" onPress={close} /> : null
                            }
                        </View>}
                </SafeAreaView>
                <PhotoPicker multiple={true} menuType='alert' photoSourceMenuOpened={photoSourceMenuOpened} onReceivedPhotoResult={result => addPhoto(result)} cancel={() => togglePhotoSourceMenu(false)} />


                <ViewShot style={{ width: imgWidth + 20, height: imgHeight + 20, position: 'absolute', right: -2000 }} ref={capture} >
                    {/* {console.log("newLandmark is " + newLandmark)} */}
                    {newLandmark == null || newLandmark.floor == null || newLandmark.landmark_type == null ? <></> :
                        <View style={styles.container}>
                            <Svg>
                                <IndoorFloor floorNum={newLandmark.floor} />
                                <ImageSVG x={newLandmark.longitude * imgWidth - 3} y={newLandmark.latitude * imgHeight - 3} width={imageDim} height={imageDim} href={lmTypes[newLandmark.landmark_type]['image'] as ImageSourcePropType} />
                            </Svg>
                        </View>
                    }
                </ViewShot>
            </KeyboardAvoidingView>
        </Modal>

    )
}

const styles = StyleSheet.create({
    container: {
        aspectRatio: 8 / 10,  // (caters to portrait mode) (width is 80% the value of height dimension)
        width: '100%',
        height: '100%',
        maxWidth: "100%",
        maxHeight: "100%",
        backgroundColor: "white",
        padding: 10
    }
})



export default memo(AddLandmarkPanel);
