import { ClientSideRowModelModule } from '@ag-grid-community/client-side-row-model';
import { ModuleRegistry } from '@ag-grid-community/core';
import { InfiniteRowModelModule } from '@ag-grid-community/infinite-row-model';
import { MantineProvider } from '@mantine/core';
import '@mantine/core/styles.css';
import '@mantine/dates/styles.css';
import { Notifications } from '@mantine/notifications';
import '@mantine/notifications/styles.css';
import isElectron from 'is-electron';
import { useEffect, useMemo, useRef, useState } from 'react';

import '/@/shared/styles/global.css';

import '@ag-grid-community/styles/ag-grid.css';
import 'overlayscrollbars/overlayscrollbars.css';

import i18n from '/@/i18n/i18n';
import { useDiscordRpc } from '/@/renderer/features/discord-rpc/use-discord-rpc';
import { PlayerProvider } from '/@/renderer/features/player/context/player-context';
import { WebAudioContext } from '/@/renderer/features/player/context/webaudio-context';
import { getMpvProperties } from '/@/renderer/features/settings/components/playback/mpv-settings';
import { useServerVersion } from '/@/renderer/hooks/use-server-version';
import { IsUpdatedDialog } from '/@/renderer/is-updated-dialog';
import { AppRouter } from '/@/renderer/router/app-router';
import {
    useCssSettings,
    useHotkeySettings,
    usePlaybackSettings,
    useRemoteSettings,
    useSettingsStore,
} from '/@/renderer/store';
import { useAppTheme } from '/@/renderer/themes/use-app-theme';
import { sanitizeCss } from '/@/renderer/utils/sanitize';
import { toast } from '/@/shared/components/toast/toast';
import '/styles/overlayscrollbars.css';
import { PlayerType, WebAudio } from '/@/shared/types/types';

ModuleRegistry.registerModules([ClientSideRowModelModule, InfiniteRowModelModule]);

const mpvPlayer = isElectron() ? window.api.mpvPlayer : null;
const ipc = isElectron() ? window.api.ipc : null;
const remote = isElectron() ? window.api.remote : null;
const utils = isElectron() ? window.api.utils : null;

export const App = () => {
    const { mode, theme } = useAppTheme();
    const language = useSettingsStore((store) => store.general.language);

    const { content, enabled } = useCssSettings();
    const { type: playbackType } = usePlaybackSettings();
    const { bindings } = useHotkeySettings();
    // const handlePlayQueueAdd = useHandlePlayQueueAdd();
    // const { clearQueue, restoreQueue } = useQueueControls();
    const remoteSettings = useRemoteSettings();
    const cssRef = useRef<HTMLStyleElement | null>(null);
    useDiscordRpc();
    useServerVersion();

    const [webAudio, setWebAudio] = useState<WebAudio>();

    useEffect(() => {
        if (enabled && content) {
            // Yes, CSS is sanitized here as well. Prevent a suer from changing the
            // localStorage to bypass sanitizing.
            const sanitized = sanitizeCss(content);
            if (!cssRef.current) {
                cssRef.current = document.createElement('style');
                document.body.appendChild(cssRef.current);
            }

            cssRef.current.textContent = sanitized;

            return () => {
                cssRef.current!.textContent = '';
            };
        }

        return () => {};
    }, [content, enabled]);

    // const providerValue = useMemo(() => {
    //     return { handlePlayQueueAdd };
    // }, [handlePlayQueueAdd]);

    const webAudioProvider = useMemo(() => {
        return { setWebAudio, webAudio };
    }, [webAudio]);

    // Start the mpv instance on startup
    useEffect(() => {
        const initializeMpv = async () => {
            if (playbackType === PlayerType.LOCAL) {
                const isRunning: boolean | undefined = await mpvPlayer?.isRunning();

                mpvPlayer?.stop();

                if (!isRunning) {
                    const extraParameters = useSettingsStore.getState().playback.mpvExtraParameters;
                    const properties: Record<string, any> = {
                        // speed: usePlayerStore.getState().speed,
                        ...getMpvProperties(useSettingsStore.getState().playback.mpvProperties),
                    };

                    await mpvPlayer?.initialize({
                        extraParameters,
                        properties,
                    });

                    mpvPlayer?.volume(properties.volume);
                }
            }

            utils?.restoreQueue();
        };

        if (isElectron()) {
            initializeMpv();
        }

        return () => {
            mpvPlayer?.stop();
            mpvPlayer?.cleanup();
        };
    }, [playbackType]);

    useEffect(() => {
        if (isElectron()) {
            ipc?.send('set-global-shortcuts', bindings);
        }
    }, [bindings]);

    // useEffect(() => {
    //     if (utils) {
    //         utils.onSaveQueue(() => {
    //             const { current, queue } = usePlayerStore.getState();
    //             const stateToSave: Partial<Pick<PlayerState, 'current' | 'queue'>> = {
    //                 current: {
    //                     ...current,
    //                     status: PlayerStatus.PAUSED,
    //                 },
    //                 queue,
    //             };
    //             utils.saveQueue(stateToSave);
    //         });

    //         utils.onRestoreQueue((_event: any, data) => {
    //             const playerData = restoreQueue(data);
    //             if (playbackType === PlaybackType.LOCAL) {
    //                 setQueue(playerData, true);
    //             }
    //             updateSong(playerData.current.song);
    //         });
    //     }

    //     return () => {
    //         ipc?.removeAllListeners('renderer-restore-queue');
    //         ipc?.removeAllListeners('renderer-save-queue');
    //     };
    // }, [playbackType, restoreQueue]);

    useEffect(() => {
        if (remote) {
            remote
                ?.updateSetting(
                    remoteSettings.enabled,
                    remoteSettings.port,
                    remoteSettings.username,
                    remoteSettings.password,
                )
                .catch((error) => {
                    toast.warn({ message: error, title: 'Failed to enable remote' });
                });
        }
        // We only want to fire this once
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, []);

    useEffect(() => {
        if (language) {
            i18n.changeLanguage(language);
        }
    }, [language]);

    return (
        <MantineProvider defaultColorScheme={mode as 'dark' | 'light'} theme={theme}>
            <Notifications
                containerWidth="300px"
                position="bottom-center"
                styles={{
                    root: {
                        marginBottom: 90,
                    },
                }}
                zIndex={50000}
            />
            <WebAudioContext.Provider value={webAudioProvider}>
                <PlayerProvider>
                    <AppRouter />
                </PlayerProvider>
            </WebAudioContext.Provider>
            <IsUpdatedDialog />
        </MantineProvider>
    );
};
