/////////////////////////////////////////////////////////////////////
//                           Module imports                        //
/////////////////////////////////////////////////////////////////////
import * as React from 'react';
import { 
    StyleSheet, 
    SafeAreaView,
    ScrollView,
    View, 
    TouchableOpacity,
    TouchableHighlight,
    Text, 
    Dimensions,
    TextInput,
    FlatList,
    Button,
    Keyboard
} from 'react-native';
import { Icon } from 'react-native-elements';
import { MaterialIndicator } from 'react-native-indicators';

/////////////////////////////////////////////////////////////////////
//                           Local imports                         //
/////////////////////////////////////////////////////////////////////

// Theme
import colors from '../../styles/colors';
import typography from '../../styles/typography';

/////////////////////////////////////////////////////////////////////
//                              Styling                            //
/////////////////////////////////////////////////////////////////////
const screenWidth = Math.round(Dimensions.get('window').width);
const screenHeight = Math.round(Dimensions.get('window').height);

const styles = StyleSheet.create({
    container: {
        position: 'absolute',
        flexDirection: 'column',
        justifyContent: 'center',
        zIndex: 5
    },
    parent: {
        marginTop: 12,
        borderWidth: 1,
        borderRadius: 5,
        borderColor: colors.onsurface_disabled,
        paddingLeft: 8,
        paddingRight: 4,
        flexDirection: "row",
        justifyContent: "space-between",
        width: screenWidth * 0.905,
    },
    focusedParent: {
        marginTop: 12,
        borderWidth: 1,
        borderRadius: 5,
        borderColor: colors.onsurface_disabled,
        paddingLeft: 8,
        flexDirection: "row",
        justifyContent: "space-between",
        backgroundColor: colors.onprimary_highEmphasis,
        width: screenWidth * 0.905
    },
    searchBar: {
        height: 38,
        width: '89%',
        backgroundColor: 'transparent',
        alignSelf: "center",
    },
    focusedSearchBar: {
        height: 38,
        width: '89%',
        backgroundColor: colors.onprimary_highEmphasis
    },
    clearBtn: {
        justifyContent: "center",
        alignSelf: "center",
        marginRight: 4,
    },
    focusedClearBtn: {
        justifyContent: "center",
        alignSelf: "center",
        marginRight: 8,
        marginTop: 2
    },
    dropdown: {
        position: "relative",
        backgroundColor: colors.onprimary_highEmphasis,
        width: screenWidth * 0.904,
        height: screenHeight * 0.18,
        alignItems: "flex-start",
        justifyContent: "flex-start",
        elevation: 8,
        paddingTop: 4,
        zIndex: 100,
    },
    ghostInput: {
        top: screenHeight,
        display: "none"
    },
    dropdownItem: {
        paddingTop: 6,
        paddingBottom: 6,
        width: screenWidth * 0.91,
    },
    dropdownItemTitle: {
        fontSize: 14,
        paddingTop: 2,
        paddingLeft: 13,
        paddingRight: 13,
        paddingBottom: 2
    },
    loadingIndicator: {
        alignItems: "center",
        justifyContent: "center",
        paddingLeft: (screenWidth * 0.85) / 2
    },
    noResults: {
        width: screenWidth * 0.904,
        height: screenHeight * 0.14,
        alignItems: "center",
        justifyContent: "center"
    }
});


/////////////////////////////////////////////////////////////////////
//                            API Search                           //
/////////////////////////////////////////////////////////////////////
const searchCharacters = async ( search ) => {
    try {
        const response = await fetch(
            `https://clinicaltables.nlm.nih.gov/api/rxterms/v3/search?terms=${search.toLowerCase()}&ef=STRENGTHS_AND_FORMS`
        );

        const data = await response.json();

        return data; 
    } catch (error) {
        console.log(`error ocurred: ${error}`);
    }
}

// Hook
const useDebounce = ( value, delay ) => {
    const [debouncedValue, setDebouncedValue] = React.useState(value);
    React.useEffect(
        () => {
        // Update debounced value after delay
        const handler = setTimeout(() => {
            setDebouncedValue(value);
        }, delay);
        // Cancel the timeout if value changes (also on delay change or unmount)
        // This is how we prevent debounced value from updating if value is changed ...
        // .. within the delay period. Timeout gets cleared and restarted.
        return () => {
            clearTimeout(handler);
        };
        },
        [value, delay] // Only re-call effect if value or delay changes
    );
    return debouncedValue;
}

/////////////////////////////////////////////////////////////////////
//                     Auto Complete Search Bar                    //
/////////////////////////////////////////////////////////////////////
const AutoSearchBar = (props) => {
    // Search term
    const [searchTerm, setSearchTerm] = React.useState("");
    // Text to display in search bar
    const [text, onChangeText] = React.useState("");
    // API search results
    const [searchResults, setSearchResults] = React.useState(['']);
    // Searching status (whether there is pending API request)
    const [isSearching, setIsSearching] = React.useState(false);
    // Keep track of search bar focus
    const [hasFocus, onChangeFocus] = React.useState(false);
    const [showingDropdown, setShowingDropdown] = React.useState(false);
    // Dropdown item id
    const [selectedId, setSelectedId] = React.useState(null);
    const [dropdownData, setDropdownData] = React.useState(null);
    
    // Debounce search term so that it only gives us latest value ...
    // ... if searchTerm has not been updated within last 500ms.
    // The goal is to only have the API call fire when user stops typing ...
    // ... so that we aren't hitting our API rapidly.
    const debouncedSearchTerm = useDebounce(searchTerm, 500);

    const toggleDropdown = () => {
        setShowingDropdown(!showingDropdown);
    };

    const hideDropdown = () => {
        setShowingDropdown(false);
    };

    const renderDropdownItem = ({ item }) => (
        <TouchableHighlight 
            style={styles.dropdownItem}
            underlayColor={colors.surface_overlay}
            onPress={() => {
                onChangeText(item.name + ' (' + item.dose + ')');
                props.onSelectionChange(item.name, item.form)
                Keyboard.dismiss();
            }} 
        >
            <Text style={styles.dropdownItemTitle} >
                {item.name + ' (' + item.dose + ')'}
            </Text>
        </TouchableHighlight>
    );
    
    const renderDropdown = () => {

        return (
            <View style={styles.dropdown}>
                {isSearching && (
                    <MaterialIndicator 
                        color={colors.surface_overlay} 
                        size={20}
                        style={styles.loadingIndicator}
                    />
                )}
                {!isSearching && (
                    <FlatList
                        data={searchResults}
                        renderItem={renderDropdownItem}
                        ListFooterComponent={(
                            <View style={{height: 12}}></View>
                        )}
                        ListEmptyComponent={(
                            <View style={styles.noResults}>
                                <Text style={{...typography.subtitle}}>No medications found</Text>
                            </View>
                        )}
                        keyExtractor={item => item.id}
                        extraData={searchResults}
                        keyboardShouldPersistTaps={'handled'}
                        nestedScrollEnabled
                    />
                )}
                <View style={{height: 12}}></View>
            </View>
        );
    };

    const onSearchBarFocus = () => {
        onChangeFocus(true);

        if(text !== '') {
            toggleDropdown();
        }
    }

    const onSearchBarBlur = () => {
        onChangeFocus(false);
        setShowingDropdown(false);
    }

    // What to do when text is being typed
    const onSearchBarTextChange = (text) => {
        if(text !== '' && !showingDropdown) {
            toggleDropdown();
        } else if(text === '' && showingDropdown){
            toggleDropdown();
        }
    }

    const clearSearchBarTxt = () => {
        onChangeText('');
        hideDropdown();
    }

    const prettifySearchResults = (results) => {
        const suggestions = [];

        // Only prettify if a non-empty result is returned from API
        if (results.toString()[0] !== '0'){
            // Get the list of medication names
            const medicationNames = results[1].map(res