import { FontAwesome } from "@expo/vector-icons";
import { ImageInfo } from "expo-image-picker/build/ImagePicker.types";
import React, { MutableRefObject, useState } from "react";
import { ActivityIndicator, FlatList, Image, ScrollView, StyleSheet, Text, TextInput, TouchableOpacity, View } from "react-native";
import Picker from "react-native-picker-select";
import { QueryStatus } from "react-query";
import { LMComment } from "../../../../hooks/useComments";
import { Landmark, LMPhoto, useLandmarks } from "../../../../hooks/useLandmarks";
import { lmTypes } from "../../../../utils/GlobalUtils";
import { IconButton, PrimaryButton } from "../../../Buttons";
import { PhotoPicker } from "../../../PhotoPicker";
import { Separator } from "../../../Separator";
import { CommentsContainer } from "./CommentsContainer";

interface DetailsBodyProps {
    editingEnabled: boolean,
    updatedLandmark?: Landmark,
    landmark?: Landmark,
    setUpdatedLandmark: (landmark: Landmark) => void,
    comments?: LMComment[],
    commentListRef: MutableRefObject<FlatList>
    commentTextInputRef: MutableRefObject<TextInput>
    focusedCommentId?: string,
    focusComment: (id: string) => void,
    startEditingComment: (comment: LMComment) => void,
    deleteComment: (id: string) => void
    commentBeingEdited?: LMComment, 
    setCommentBeingEdited: (comment: LMComment) => void,
    setNewComment: (commentId: string) => void,
    newCommentId?: string,
    editComment: (comment: LMComment) => void,
    addComment: () => void
    setSelectedImage: (index: number) => void 
    tryDeletePhoto: (photoId: string) => void
    deletePhotoStatus: QueryStatus 
    toggleLmDetails: (state: boolean) => void
    setKeyboardOpened: (state: boolean) => void
    keyboardOpened: boolean
    profileId: string
}

/**
 * Component that renders the body of the Landmark details panel
*/
export const DetailsBody: React.FC<DetailsBodyProps> = (props) => {
    const { addPhoto, addPhotoStatus } = useLandmarks()

    /**
     * Flag that sets whether a new photo is being chosen and processed
    */
    const processingPhotoState = false
    const [processingPhoto, toggleProcessingPhoto] = useState<boolean>(processingPhotoState)
    /**
     * Flag that toggles the photo source menu being displayed
    */
    const photoSourceMenuOpenedState = false
    const [photoSourceMenuOpened, togglePhotoSourceMenu] = useState<boolean>(photoSourceMenuOpenedState) 

    /**
     * Handles selection of a selected photo. Adds the photo data to the database.
    */
    const _onPhotoSelected = async (result: ImageInfo) => {
        togglePhotoSourceMenu(false)
        const photo: LMPhoto = {id: '', image_b64: 'data:image/png;base64,' + result.base64, height: result.height, width: result.width, landmark: props.landmark?.id}
        await addPhoto(photo)
        toggleProcessingPhoto(false)
    }

    /**
     * Sets given image as selected photo to be maximized on the screen
     * @param 
     */
    const maximizePhoto = (i: number): void => {
        if (!props.editingEnabled) {
            props.setSelectedImage(i)
        }
        else {
            console.log('editing is enabled, can\'t maximize image')
        }
    }

    /**
     * Sub-component that renders picker for landmark types
     * @param 
     */
    const LandmarkTypePicker: React.FC = () => {
        return (
        <View style={{flexDirection: 'row', marginBottom: 20, justifyContent: "space-between"}}> 
            {props.updatedLandmark?.landmark_type ? 
            <>
                <Picker
                    style={{
                        inputIOS: {color: 'white'}, 
                        inputAndroid: {color: 'white'},
                        iconContainer: {flex: 1, justifyContent: 'center', height: '100%'},
                        viewContainer: {padding: 5, elevation: 1, flex: 1, justifyContent: 'center'}, placeholder: {color: 'white'}}}
                    placeholder={{}}
                    value={props.updatedLandmark?.landmark_type}
                    onValueChange={(value) => {
                        props.setUpdatedLandmark({...props.updatedLandmark, landmark_type: value, title: lmTypes[value].label})
                    }}
                    useNativeAndroidPickerStyle={true}
                    items={Object.keys(lmTypes)?.filter(icon => parseInt(icon) != props.landmark?.landmark_type).map(icon => {
                        return (
                            {label: lmTypes[parseInt(icon)].label.toUpperCase(), value: icon, key: icon}
                        )})} />
                {props.updatedLandmark ? <Image style={{marginLeft: 20}} source={lmTypes[props.updatedLandmark?.landmark_type].image}/> : null}
            </>
            : null}
        </View>
        )
    }

    /**
     * Sub-component that renders the view to be displayed when editing is disabled
     * @param 
     */
    const EditingDisabledUpperView: React.FC = () => {
        return (
            <View style={{flexDirection: 'row', justifyContent: 'space-between'}}>
                <View style={{flex: 8, flexDirection: 'column', marginBottom: 20}}>
                    <Text style={{color: 'white', marginBottom: 10, fontSize: 15}}>{lmTypes[props.landmark?.landmark_type]?.label.toUpperCase()}</Text>
                    <ScrollView nestedScrollEnabled={true}>
                        <Text style={{color: 'white', fontSize: 13}}>{props.landmark?.description}</Text>
                    </ScrollView>
                </View>
                {props.landmark?.landmark_type ? <Image source={lmTypes[props.landmark?.landmark_type].image} /> : null}
            </View>
        )
    }

    return (
        <ScrollView nestedScrollEnabled={true} contentContainerStyle={{justifyContent: 'space-between'}} style={{flex: 1, marginHorizontal: 20}}>
            {props.editingEnabled ?
            <>
                <LandmarkTypePicker />
                <Separator style={{marginBottom: 20, opacity: .5}} color="lightgray" />
                <Text style={{color: 'white', marginBottom: 10}}>Description</Text>
                <ScrollView nestedScrollEnabled={true} style={{backgroundColor: 'white'}}>
                    <TextInput 
                        multiline={true} 
                        style={[styles.input, {fontSize: 13, marginBottom: 10}]}
                        onChangeText={text => props.setUpdatedLandmark({...props.updatedLandmark, description: text})} 
                        value={props.updatedLandmark.description}/>
                </ScrollView>
            </>: <EditingDisabledUpperView />}
            {!props.editingEnabled ?
            <CommentsContainer
                setKeyboardOpened={props.setKeyboardOpened}
                keyboardOpened={props.keyboardOpened}
                comments={props.comments}
                focusComment={props.focusComment}
                focusedCommentId={props.focusedCommentId}
                commentListRef={props.commentListRef}
                commentTextInputRef={props.commentTextInputRef}
                commentBeingEdited={props.commentBeingEdited}
                addComment={props.addComment}
                setCommentBeingEdited={props.setCommentBeingEdited}
                setNewComment={props.setNewComment}
                newCommentId={props.newCommentId}
                editComment={props.editComment}
                startEditingComment={props.startEditingComment}
                deleteComment={props.deleteComment} /> : null}
            {!props.keyboardOpened && props.profileId == props.landmark?.user ? 
            <>
                {props.deletePhotoStatus == 'loading' || 
                props.deletePhotoStatus == 'error' || 
                addPhotoStatus == "loading" || 
                addPhotoStatus == "error" ||
                processingPhoto ?
                <View style={{justifyContent: "space-evenly", alignItems: "center"}}>
                    <Text style={{color: 'white', fontSize: 20, marginBottom: 40}}>{
                        props.deletePhotoStatus == "loading" || addPhotoStatus == "loading" ? "Loading photos" :
                        props.deletePhotoStatus == "error" || addPhotoStatus == "error" ? "There was an error loading photos" : 
                        processingPhoto ? "Processing photo" : null
                    }</Text>
                    {
                        props.deletePhotoStatus == 'loading' || addPhotoStatus == "loading" || processingPhoto ? <ActivityIndicator color='white' size="large"/> :
                        props.deletePhotoStatus == 'error' || addPhotoStatus == "error" ? <PrimaryButton text="Okay" style={{borderColor: 'white', borderWidth: 1}} onPress={() => props.toggleLmDetails(false)} /> : null
                    }
                </View> : props.landmark?.photos?.length > 0 ? 
                <>
                    <ScrollView nestedScrollEnabled={true} style={{flexDirection: 'row', marginBottom: 5, }} horizontal={true}>
                        {props.landmark?.photos?.length < 5 ? <IconButton style={{alignSelf: 'center', padding: 10, opacity: .5, marginLeft: 10}} color='white' size={30} icon="plus" onPress={() => togglePhotoSourceMenu(true)} />: null}
                        {props.landmark?.photos.map((photo, i) => {    
                            
                            return (
                                <TouchableOpacity activeOpacity={1} key={i} style={{marginHorizontal: 1, padding: 14, zIndex: 11}} onPress={() => maximizePhoto(i)}>
                                    <Image style={{alignSelf: 'center', height: 300, width: 200}} source={{uri: 'data:image/png;base64,' + photo.image_b64}}/> 
                                    <IconButton icon="times-circle" color="lightgray" style={{position: 'absolute', top: -2, right: 0}} size={25} onPress={() => props.tryDeletePhoto(photo.id)} />
                                </TouchableOpacity>
                            )
                        })}
                    </ScrollView>
                </> : 
                <TouchableOpacity style={{marginTop: 30, justifyContent: 'center', alignItems: 'center', opacity: .7}} onPress={() => togglePhotoSourceMenu(true)}>
                    <Text style={{fontSize: 20, marginBottom: 10, color: 'white'}}>Add photo</Text>
                    <FontAwesome name="plus" size={30} color='white' />
                </TouchableOpacity>}
            </> : null}
            <PhotoPicker multiple={true} menuType="alert" onReceivedPhotoResult={async result => await _onPhotoSelected(result)} photoSourceMenuOpened={photoSourceMenuOpened} onBeforeLaunchPicker={() => toggleProcessingPhoto(true)} cancel={() => {toggleProcessingPhoto(false) ; togglePhotoSourceMenu(false)}}/> 
        </ScrollView>
    )
}

const styles = StyleSheet.create({
    input: {
        padding: 5,
        color: 'black'
    },
    commentContainer: {
        flex: 5,
        marginBottom: 40,
    },
})
