import React, {useEffect, useCallback, useState, useRef} from 'react';
import {
    Image,
    useWindowDimensions,
    View,
    AppState,
    StatusBar,
    Platform,
    TouchableOpacity,
    Modal,
} from 'react-native';
import Orientation from 'react-native-orientation-locker';
import SystemNavigationBar from 'react-native-system-navigation-bar';
import {SourceType} from '../../source';
import {PlayerView} from '../../components/PlayerView';
import {usePlayer} from '../../hooks';
import {AdSourceType} from '../../advertising';
import {FullscreenHandler} from '../../ui';
import {useNavigation} from '@react-navigation/native';
import IonIcon from 'react-native-vector-icons/Ionicons';
import {ReplayIcon} from '../Icons';
import {styles, fullscreenBlock, landscapeBlock} from './styles';

class SampleFullscreenHandler implements FullscreenHandler {
    isFullscreenActive: boolean = true;
    onFullscreen: (fullscreenMode: boolean) => void;

    constructor(
        isFullscreenActive: boolean,
        onFullscreen: (fullscreenMode: boolean) => void,
    ) {
        this.isFullscreenActive = isFullscreenActive;
        this.onFullscreen = onFullscreen;
    }

    enterFullscreen(): void {
        if (Platform.OS === 'android') {
            SystemNavigationBar.stickyImmersive(true);
        } else {
            StatusBar.setHidden(true);
        }
        this.onFullscreen(true);
        this.isFullscreenActive = true;
        Orientation.lockToLandscape();
    }

    exitFullscreen(): void {
        if (Platform.OS === 'android') {
            SystemNavigationBar.stickyImmersive(false);
        } else {
            StatusBar.setHidden(false);
        }
        this.onFullscreen(false);
        this.isFullscreenActive = false;
        Orientation.lockToPortrait();
    }
}

interface BitmovinConfig {
    playerKey: string;
    analyticsKey: string;
    supplementalPlayerUiCss: string;
}

export interface VideoPlayerProps {
    bitmovinConfig?: BitmovinConfig;
    onAdStarted?: () => void;
    onAdCompleted?: () => void;
    onPlay?: () => void;
    onPaused?: () => void;
    onEnd?: () => void;
    setActivePlayerID?: (ref: string) => void;
    onError?: (err: any) => void;
    adTagUrl?: string;
    videoUri?: string;
    thumbUrl?: string;
    testID?: string;
    allowUseNavigation?: boolean;
    autostart?: boolean;
    autoPlayNextEnabled?: boolean;
    activePlayerID?: string;
    playerID?: string;
    width?: number;
    galleryIndex?: number;
    selectedGalleryIndex?: number;
    externalStyles?: any;
    setFullscreenModeRedux?: (data: boolean) => void;
    isExpandedAlerts?: boolean;
}

const VideoPlayer = ({
    videoUri,
    onAdCompleted,
    onAdStarted,
    onError,
    onPlay,
    onPaused,
    thumbUrl,
    onEnd,
    adTagUrl,
    autostart,
    allowUseNavigation,
    setActivePlayerID,
    activePlayerID,
    playerID,
    setFullscreenModeRedux,
    galleryIndex,
    selectedGalleryIndex,
    bitmovinConfig,
    autoPlayNextEnabled,
    externalStyles,
    isExpandedAlerts,
}: VideoPlayerProps): React.ReactElement | null => {
    const [isOverlayVisible, setIsOverlayVisible] = useState(!autostart);
    const [isReplayButtonVisible, setIsReplayButtonVisible] = useState(false);
    const [fullscreenMode, setFullscreenMode] = useState(false);
    const fullscreenHandler = useRef(
        new SampleFullscreenHandler(
            fullscreenMode,
            (isFullscreenModeActive: boolean) => {
                setFullscreenModeRedux?.(isFullscreenModeActive);
                setFullscreenMode(isFullscreenModeActive);
            },
        ),
    ).current;
    const {width, height} = useWindowDimensions();

    const navigation = allowUseNavigation && useNavigation();

    const player =  bitmovinConfig?.analyticsKey && usePlayer({
        licenseKey: bitmovinConfig?.playerKey,
        analyticsConfig: {
            key: bitmovinConfig.analyticsKey,
            playerKey: bitmovinConfig?.playerKey,
        },
        styleConfig: {
        supplementalPlayerUiCss:
            bitmovinConfig?.supplementalPlayerUiCss,
        },
    });

    useEffect(() => {
        const subscription = AppState.addEventListener(
            'change',
            (nextAppState) => {
                if (nextAppState === 'background' && player) {
                    player.pause();
                }
            },
        );
        return () => {
            subscription.remove();
        };
    }, []);

    useEffect(() => {
        if (videoUri && player) {
            player.load({
                url: videoUri,
                type: SourceType.HLS,
            });
        }
        return () => {
            player && player.destroy();
        };
    }, [player]);

    useEffect(() => {
        if (
            playerID !== activePlayerID ||
            galleryIndex !== selectedGalleryIndex
        ) {
            player && player.pause();
        }
        if (autostart) {
            setTimeout(() => {
                setIsOverlayVisible(false);
                if (videoUri && player) {
                    player.load({
                        url: videoUri,
                        type: SourceType.HLS,
                    });
                }
                player && player.play();
            }, 1);
        }
        if (navigation) {
            return navigation.addListener('blur', () => {
                player && player.pause();
            });
        }
    }, [
        activePlayerID,
        playerID,
        player,
        galleryIndex,
        selectedGalleryIndex,
        navigation,
        videoUri,
        autostart,
    ]);

    useEffect(()=>{
        player && player.pause();
    }, [player, isExpandedAlerts])

    const onReady = useCallback(() => {
        if (player) {
            if (adTagUrl) {
                player.scheduleAd({
                     sources: [
                       {
                         tag: adTagUrl,
                         type: AdSourceType.IMA,
                       },
                     ],
                   });
            }
            if (autostart) {
                setIsOverlayVisible(false);
                player && player.play();
            }
        }
    }, [player, autostart, adTagUrl]);

    const onPlayerError = useCallback(
        (err: any) => {
            onError?.(err);
        },
        [onError],
    );

    const onPlaybackFinished = useCallback(() => {
        if (fullscreenMode) {
            if (Platform.OS === 'android') {
                SystemNavigationBar.stickyImmersive(false);
            } else {
                StatusBar.setHidden(false);
            }
            setFullscreenModeRedux?.(false);
            setFullscreenMode(false);
            Orientation.lockToPortrait();
        }
        if (!autoPlayNextEnabled) {
            setIsReplayButtonVisible(true);
        }
        onEnd?.();
    }, [onEnd, fullscreenMode, autoPlayNextEnabled, setFullscreenModeRedux, setFullscreenMode, setIsReplayButtonVisible]);

    const handlePlay = useCallback(() => {
        setIsOverlayVisible(false);
        player && player.play();
    }, [player]);

    const handlePlaying = useCallback(() => {
        if (playerID) {
            setActivePlayerID?.(playerID);
        }
    }, [setActivePlayerID, playerID]);

    const handleAdStarted = useCallback(()=>{
        onAdStarted?.();
        if (playerID) {
            setActivePlayerID?.(playerID);
        }
    }, [onAdStarted, setActivePlayerID, playerID])

    const handleReplay = useCallback(()=>{
        player && player.seek(0);
        player && player.play();
        setIsReplayButtonVisible(false);
    }, [player, setIsReplayButtonVisible]);

    const renderPlayer = () => {
        return player && fullscreenHandler && (
            <PlayerView
                style={styles.block}
                player={player}
                onReady={onReady}
                onAdFinished={onAdCompleted}
                onAdSkipped={onAdCompleted}
                onAdStarted={handleAdStarted}
                onPlayerError={onPlayerError}
                onPlay={onPlay}
                onPlaying={handlePlaying}
                onPaused={onPaused}
                onPlaybackFinished={onPlaybackFinished}
                isFullscreenRequested={fullscreenMode}
                fullscreenHandler={fullscreenHandler}
            />
        );
    };

    return (
        <View
            style={[
                externalStyles,
                fullscreenMode
                    ? fullscreenBlock(width, height)
                    : landscapeBlock(width),
            ]}>
            {!fullscreenMode && (
                <View>
                    {renderPlayer()}
                    {isOverlayVisible && (
                        <TouchableOpacity
                            style={styles.overlayBlock}
                            onPress={handlePlay}>
                            <IonIcon
                                name="play-circle-outline"
                                style={styles.overlayIcon}
                            />
                            <Image
                                style={styles.block}
                                source={{uri: thumbUrl}}
                            />
                        </TouchableOpacity>
                    )}
                    {isReplayButtonVisible && (
                        <View style={styles.overlayBlock}>
                              <TouchableOpacity style={styles.overlayIcon} onPress={handleReplay}>
                                <ReplayIcon />
                            </TouchableOpacity>
                             <Image
                                style={styles.block}
                                source={{uri: thumbUrl}}
                            />
                            <View style={styles.background} />
                        </View>
                    )}
                </View>
             )} 
            <Modal supportedOrientations={['landscape', 'portrait']} statusBarTranslucent={true} visible={fullscreenMode}>
                {renderPlayer()}
            </Modal>
        </View>
    );
};

export default VideoPlayer;
