import { Component, ReactNode } from 'react';
import * as React from 'react';
import videojs from 'video.js';
import '~/video.js/dist/video-js.min.css';
import browserService from '../../services/browserService';
import VjsVideoPlayerControls, { IVjsVideoPlayerControlsOptions } from './controls/vjsVideoPlayerControls';
import VjsVideoPlayerInfo, { IVjsVideoPlayerInfoOptions } from './controls/vjsVideoPlayerInfo';

interface IVideoPlayerProps {
    videoJsOptions: videojs.PlayerOptions;
    videoTitle: string;
    customControls: boolean;
    onStarted: () => void;
    onThreeSecondsWatched?: () => void;
    onEnded: () => void;
    onCompleted: () => void;
    customClass?: string;
    controlBar?: boolean;
}

export class VideoPlayer extends Component<IVideoPlayerProps, {}> {
    private player: videojs.Player;
    private isPlaying: boolean;
    private videoNode: HTMLVideoElement | null;
    private onVideoUnloaded: () => void;
    private threeSecondsWatched: boolean;

    constructor(props: IVideoPlayerProps) {
        super(props);
        this.onVideoUnloaded = this.onVideoUnload.bind(this);
    }

    public componentDidMount() {
        const playerOptions = this.props.videoJsOptions;
        playerOptions.controlBar = this.props.controlBar ? {} : false;
        (playerOptions as any).bigPlayButton = this.props.controlBar;

        this.player = videojs(this.videoNode, playerOptions, (this.props.controlBar ? () => { } : this.addCustomControls.bind(this)));
        this.player.one('play', () => this.props.onStarted());
        this.player.on('play', () => this.isPlaying = true);
        this.player.on('timeupdate', this.onTimeUpdate);
        this.player.on('ended', () => {
            this.isPlaying = false;
            this.onVideoComplete();
        });
        if (browserService.isIos()) {
            window.addEventListener('pagehide', this.onVideoUnloaded);
        } else {
            window.addEventListener('beforeunload', this.onVideoUnloaded);
        }
    }

    public componentWillUnmount() {
        if (this.isPlaying) {
            this.props.onEnded();
        }
        if (this.player) {
            this.player.dispose();
        }
        window.removeEventListener('pagehide', this.onVideoUnloaded);
        window.removeEventListener('beforeunload', this.onVideoUnloaded);
    }

    public render(): ReactNode {
        return (
            <div className={`${this.props.customClass || 'ns-video-initial'} animated fadeIn`}>
                <div className='embed-responsive embed-responsive-16by9'>
                    <div data-vjs-player>
                        <video ref={(node) => this.videoNode = node} className='video-js embed-responsive-item' playsInline></video>
                    </div>
                </div>
            </div>
        );
    }

    private addCustomControls(): void {
        this.player.addChild(VjsVideoPlayerInfo.ComponentName, { title: this.props.videoTitle, displayTime: this.props.customControls } as IVjsVideoPlayerInfoOptions);
        this.player.addChild(VjsVideoPlayerControls.ComponentName, { displayMuteToggle: this.props.customControls, displayPlayButton: true, displayFullscreenToggle: this.props.customControls } as IVjsVideoPlayerControlsOptions);
    }

    private onVideoComplete() {
        if (this.player.isFullscreen()) {
            this.player.exitFullscreen();
        }
        this.props.onCompleted();
    }

    private onVideoUnload() {
        this.props.onEnded();
    }

    private onTimeUpdate = () => {
        if (!this.threeSecondsWatched && Math.floor(this.player.currentTime()) >= 3 && this.props.onThreeSecondsWatched) {
            this.threeSecondsWatched = true;
            this.props.onThreeSecondsWatched();
        }
    }
}