import { NavigatorInitComposer, NavigatorSearchComposer, RoomInfoComposer, RoomSessionEvent } from 'nitro-renderer';
import { FC, useCallback, useEffect, useReducer, useState } from 'react';
import { GetRoomSessionManager } from '../../api';
import { NavigatorEvent } from '../../events';
import { useRoomSessionManagerEvent } from '../../hooks/events/nitro/session/room-session-manager-event';
import { useUiEvent } from '../../hooks/events/ui/ui-event';
import { SendMessageHook } from '../../hooks/messages/message-event';
import { NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../layout';
import { LocalizeText } from '../../utils/LocalizeText';
import { NavigatorContextProvider } from './context/NavigatorContext';
import { NavigatorMessageHandler } from './NavigatorMessageHandler';
import { NavigatorViewProps } from './NavigatorView.types';
import { initialNavigator, NavigatorActions, NavigatorReducer } from './reducers/NavigatorReducer';
import { NavigatorSearchResultSetView } from './views/search-result-set/NavigatorSearchResultSetView';
import { NavigatorSearchView } from './views/search/NavigatorSearchView';

export const NavigatorView: FC<NavigatorViewProps> = props =>
{
    const [ isVisible, setIsVisible ] = useState(false);
    const [ navigatorState, dispatchNavigatorState ] = useReducer(NavigatorReducer, initialNavigator);
    const { needsNavigatorUpdate = false, topLevelContext = null, topLevelContexts = null } = navigatorState;

    const visitRoom = useCallback((roomId: number, password: string = null) =>
    {
        GetRoomSessionManager().createSession(roomId, password);
    }, []);

    const tryVisitRoom = useCallback((roomId: number) =>
    {
        SendMessageHook(new RoomInfoComposer(roomId, false, true));
    }, []);

    const onNavigatorEvent = useCallback((event: NavigatorEvent) =>
    {
        switch(event.type)
        {
            case NavigatorEvent.SHOW_NAVIGATOR:
                setIsVisible(true);
                return;
            case NavigatorEvent.HIDE_NAVIGATOR:
                setIsVisible(false);
                return;
            case NavigatorEvent.TOGGLE_NAVIGATOR:
                setIsVisible(value => !value);
                return;
            case NavigatorEvent.VISIT_ROOM:
                visitRoom(event.roomId, event.password);
                return;
            case NavigatorEvent.TRY_VISIT_ROOM:
                tryVisitRoom(event.roomId);
                return;
        }
    }, [ visitRoom, tryVisitRoom ]);

    useUiEvent(NavigatorEvent.SHOW_NAVIGATOR, onNavigatorEvent);
    useUiEvent(NavigatorEvent.HIDE_NAVIGATOR, onNavigatorEvent);
    useUiEvent(NavigatorEvent.TOGGLE_NAVIGATOR, onNavigatorEvent);
    useUiEvent(NavigatorEvent.VISIT_ROOM, onNavigatorEvent);
    useUiEvent(NavigatorEvent.TRY_VISIT_ROOM, onNavigatorEvent);

    const onRoomSessionEvent = useCallback((event: RoomSessionEvent) =>
    {
        switch(event.type)
        {
            case RoomSessionEvent.CREATED:
                setIsVisible(false);
                return;
        }
    }, []);

    useRoomSessionManagerEvent(RoomSessionEvent.CREATED, onRoomSessionEvent);

    useEffect(() =>
    {
        if(!isVisible || !needsNavigatorUpdate) return;
        
        dispatchNavigatorState({
            type: NavigatorActions.SET_NEEDS_UPDATE,
            payload: {
                flag: false
            }
        });
        
        SendMessageHook(new NavigatorInitComposer());

    }, [ isVisible, needsNavigatorUpdate ]);

    const sendSearch = useCallback((code: string, data: string) =>
    {
        SendMessageHook(new NavigatorSearchComposer(code, data));
    }, []);

    useEffect(() =>
    {
        if(!topLevelContexts || !topLevelContexts.length) return;

        const context = topLevelContexts[0];

        sendSearch(context.code, '');
    }, [ topLevelContexts, sendSearch ]);

    return (
        <NavigatorContextProvider value={ { navigatorState, dispatchNavigatorState } }>
            <NavigatorMessageHandler />
            { isVisible &&
                <NitroCardView className="nitro-navigator">
                    <NitroCardHeaderView headerText={ LocalizeText('navigator.title') } onCloseClick={ event => setIsVisible(false) } />
                    <NitroCardTabsView>
                        { topLevelContexts.map((context, index) =>
                            {
                                return <NitroCardTabsItemView key={ index } tabText={ LocalizeText(('navigator.toplevelview.' + context.code)) } isActive={ (topLevelContext === context) } onClick={ event => sendSearch(context.code, '') } />
                            }) }
                    </NitroCardTabsView>
                    <NitroCardContentView>
                        <NavigatorSearchView />
                        <NavigatorSearchResultSetView />
                    </NitroCardContentView>
                </NitroCardView> }
        </NavigatorContextProvider>
    );
}
