import { FontAwesome } from "@expo/vector-icons";
import * as ImagePicker from 'expo-image-picker';
import { ImageInfo } from "expo-image-picker/build/ImagePicker.types";
import React, { memo, useEffect, useState } from "react";
import { ActivityIndicator, Dimensions, Image, Platform, SafeAreaView, Text, TextInput, TouchableOpacity, View } from 'react-native';
import { ScrollView } from "react-native-gesture-handler";
import Modal from 'react-native-modal';
import { checkMultiple, PERMISSIONS, RESULTS } from "react-native-permissions";
import Picker from 'react-native-picker-select';
import { Landmark, LMPhoto, useLandmarks } from "../../../hooks/useLandmarks";
import { colors, getMediaPermissions, lmTypes } from "../../../utils/GlobalUtils";
import { IconButton, SecondaryButton } from "../../Buttons";
import { PhotoPicker } from "../../PhotoPicker";

/**
 * 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 { 
        addLandmarkAsync, 
        resetAddLm, 
        addLandmarkStatus, 
    } = useLandmarks();

    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 (addLandmarkStatus == 'success') {
                resetAddLm();
            }
        }
        resetAddMutationOnSuccess();
    }, [addLandmarkStatus]);

    useEffect(() => {
        resetAddLm();
    }, [visible]);

    /**
     * Calls {@link addLandmarkAsync} from {@link useLandmarks} to initate the process of adding a landmark, then closes the modal.
     */
    const submit = async () => {
        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={{justifyContent: "flex-end", height: '100%', margin: 0}}
            isVisible={visible} >
            <SafeAreaView style={{backgroundColor: colors.red, height: photos.length>0 ? Dimensions.get('window').height * .8 : Dimensions.get('window').height * .6}}>
                {addLandmarkStatus == 'idle' ?
                <>
                    <View style={{
                        justifyContent: 'space-between', 
                        alignItems: 'center', 
                        flexDirection: "row", 
                        marginBottom: 15, 
                        borderBottomWidth: 1, 
                        borderBottomColor: 'white', 
                        paddingHorizontal: 20, 
                        paddingVertical: 10}}>
                        <Text style={{color: 'white', fontSize: 15}}>Add landmark here?</Text>
                        <FontAwesome name="times" color='white' size={25} onPress={close} />
                    </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'}}>
                                <Picker
                                    style={{
                                        inputIOS: {color: 'white'}, 
                                        inputAndroid: {color: 'white'},
                                        viewContainer: {marginVertical: 5, flex: 1}, placeholder: {color: 'white'}}}
                                    textInputProps={{placeholderTextColor: 'white', selectionColor: 'white'}}
                                    Icon={() => <FontAwesome name="chevron-down" color='white' size={20} />}
                                    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'})
                                        }
                                    }}
                                    useNativeAndroidPickerStyle={true}
                                    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 ? 
                        <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}}>{
                        addLandmarkStatus == "loading" ? 'Uploading landmark...' :
                        addLandmarkStatus == "error" ? 'Something went wrong when trying to upload the landmark.' : null }
                    </Text>
                    {
                        addLandmarkStatus == "loading" ? <ActivityIndicator color='white' size="large"/> :
                        addLandmarkStatus == "error" ? <SecondaryButton text="Okay" onPress={close}/> : null
                    }
                </View> }
            </SafeAreaView>
            <PhotoPicker multiple={true} menuType='alert' photoSourceMenuOpened={photoSourceMenuOpened} onReceivedPhotoResult={result => addPhoto(result)} cancel={() => togglePhotoSourceMenu(false)} />
        </Modal>
    )
}

export default memo(AddLandmarkPanel);