import { FontAwesome } from '@expo/vector-icons';
import { BottomTabBarOptions, BottomTabNavigationProp, createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import { observer } from "mobx-react";
import React, { useEffect } from "react";
import { AppState, Platform, SafeAreaView, View, Text } from 'react-native';
import Map from "../components/Map/MainMapComponent/Map";
import Profile from "../components/Profile/Profile";
import { colors } from "../utils/GlobalUtils";
import  {check, checkMultiple, PERMISSIONS, requestMultiple} from 'react-native-permissions'
import { Feed } from '../components/Feed/Feed';
import { authStore } from '../stores/AuthStore';
import { getItemAsync } from 'expo-secure-store';
import Constants from 'expo-constants';
import * as Notifications from 'expo-notifications'
import { useAuth } from '../hooks/useAuth';
import { NavigationContainerRef, RouteProp } from '@react-navigation/native';
import { QueryClient, useQuery } from 'react-query';
import { useProfile } from '../hooks/useProfile';
import { NotifType } from '../types';
import Badge from '../components/Badge';

Notifications.setNotificationHandler({
    handleNotification: async () => ({
      shouldShowAlert: true,
      shouldPlaySound: false,
      shouldSetBadge: false,
    }),
});

const MainTabs = createBottomTabNavigator();

const tabBarOptions: BottomTabBarOptions = {
    //keyboardHidesTabBar: true,
    activeTintColor: 'white',
    activeBackgroundColor: '#e35555',
    inactiveTintColor: "lightgray",
    
    style: {backgroundColor: colors.red, height: 60, justifyContent: 'center'},
    labelStyle: {marginBottom: 7},
    iconStyle: {marginBottom: 7}
} 

/**
 * Permitted screens for the Auth tabs navigator. 
 * @category Navigation
 * @typedef
 */
 export type AuthTabskParamList = {
    Map: {selectedLandmark: string, selectedLandmarks: string[]},
    Profile: React.FC,
}

export type AuthTabsNavigationProp = BottomTabNavigationProp<AuthTabskParamList>

export const navigationRef = React.createRef<NavigationContainerRef>()

export const navigate = (name: string, params?) => {
    navigationRef.current.navigate(name, params)
}

/**
 * The root navigator for all authorized screens ({@link Map}, {@link Profile}). It uses a [React Navigation Bottom Tabs Navigator]{@link https://reactnavigation.org/docs/bottom-tab-navigator/} the main navigation mechanism.
 * @category Navigation
 * @component
 */
const AuthorizedNavigator: React.FC = () => {
    const {notifications, refetchNotifications, markNotificationAsRead } = useProfile(authStore.userId)

    const {getNotificationTokenFromServer, ensureNotificationTokenExistsOnServer} = useAuth()

    const handleNotificationInteraction = async (notifData: any) => {
        await markNotificationAsRead(notifData.notif_id)
        await refetchNotifications()
        if (notifData?.notif_type as NotifType == 'landmark-like' || notifData?.notif_type as NotifType == 'near-landmark')
            navigate('Map', {selectedLandmark: notifData.landmark_id})
        if (notifData?.notif_type as NotifType == 'near-landmarks')
            navigate('Map', {selectedLandmarks: notifData.landmarks})
    }

    const registerForPushNotificationsAsync = async () => {
        if (Constants.isDevice) {
            const { status: existingStatus } = await Notifications.getPermissionsAsync();
            let finalStatus = existingStatus;
            if (existingStatus !== 'granted') {
                const { status } = await Notifications.requestPermissionsAsync();
                finalStatus = status;
            }
            if (finalStatus !== 'granted') {
                alert('Failed to get push token for push notification!');
                await authStore.setNotificationToken('')
                return;
            }

            let token = authStore.notificationToken

            // try getting from memory
            if (!token) {
                // try getting token from SecureStore 
                token = await getItemAsync('notif-token')
                console.log('token from secure store: ' + token)
                if (token) {
                    await authStore.setNotificationToken(token)
                }
                else {
                    // try getting token from server db 
                    token = await getNotificationTokenFromServer()
                    console.log('token from server: ' + token)
                    if (token) {
                        console.log(token)
                        await authStore.setNotificationToken(token)
                    }
                    else {
                        // get new token from expo and save it to the server
                        console.log('token from expo: ' + token)
                        token = (await Notifications.getExpoPushTokenAsync()).data;      
                        await authStore.setNotificationToken(token)
                    }
                }
            }

            // ensure that notificationToken exists on the server
            await ensureNotificationTokenExistsOnServer(token, 5)

        } 
        else {
            console.log('Must use physical device for Push Notifications');
            authStore.setNotificationToken('')
            return 
        }
        
        if (Platform.OS === 'android') {
            Notifications.setNotificationChannelAsync('default', {
                name: 'default',
                importance: Notifications.AndroidImportance.MAX,
                vibrationPattern: [0, 250, 250, 250],
                lightColor: '#FF231F7C',
            });
        }   
    };
      
    useEffect(() => {
        /**
         * useEffect hook that is responsible for registering an appState "change" handler that will call {@linkcode checkToken} each time the app is opened or closed on the device.
         * @memberOf Atlas
         */
        const initializePushNotifications = async () => {
        if (authStore.userId) {
            await registerForPushNotificationsAsync()
            if (authStore.notificationToken) {
                const notifReceivedSubscription = Notifications.addNotificationReceivedListener(async notification => { 
                    await refetchNotifications()
                })
        
                const notifResponseReceivedSubscription = Notifications.addNotificationResponseReceivedListener(async response => {
                    const notifData = response.notification.request.content.data
                    handleNotificationInteraction(notifData)
                });
        
                return () => {
                    notifReceivedSubscription.remove()
                    notifResponseReceivedSubscription.remove()
                }; 
            }
        }
        }
        initializePushNotifications();
    }, [authStore.userId]);

    useEffect(() => {

    }, [])

    const getIconSize = (focused: boolean): number => {
        if (focused) {
            return 20
        }
        else {
            return 17
        } 
    }

    const renderFeedBadge = () => {
        const newNotifAmount = notifications?.filter(notif => !notif.read).length

        return newNotifAmount > 0 ? <Badge positioning={{top: 8, left: 13,}} value={newNotifAmount}/> : null
    }

    return(
        <SafeAreaView style={{height: '100%'}}>
            {/* <AdMobBanner adUnitID="ca-app-pub-3940256099942544/6300978111" /> */}
            <MainTabs.Navigator 
                sceneContainerStyle={{flex:1}}     
                initialRouteName="Map"
                tabBarOptions={tabBarOptions}>
                <MainTabs.Screen name="Map" component={Map} options={{tabBarIcon: ({color, focused}) => (<FontAwesome name={focused ? 'map' : 'map-o'} size={getIconSize(focused)} color={color} style={{marginTop: 'auto'}}/>)}}/>
                <MainTabs.Screen name="Feed" options={{tabBarIcon: ({color, focused}) => (
                    <View style={{marginTop: 'auto'}}>
                        <FontAwesome name={focused ? 'bell' : 'bell-o'} size={getIconSize(focused)} color={color} />
                        {renderFeedBadge()}
                    </View>
                )}}>
                    {() => <Feed notifications={notifications} handleNotifInteraction={handleNotificationInteraction} />}
                </MainTabs.Screen>
                <MainTabs.Screen name="Profile" component={Profile} options={{tabBarIcon: ({color, focused}) => (<FontAwesome name={focused ? 'user' : 'user-o'} size={getIconSize(focused)} color={color} style={{marginTop: 'auto'}}/>)}} />
            </MainTabs.Navigator>
        </SafeAreaView>
        
    )
}

export default observer(AuthorizedNavigator);