import React, { Component } from 'react';

import RadioButtonUncheckedIcon from '@material-ui/icons/RadioButtonUnchecked';
import LoopIcon from '@material-ui/icons/Loop';
import Fab from '@material-ui/core/Fab';
import CircularProgress from '@material-ui/core/CircularProgress';
import Dialog from '@material-ui/core/Dialog';
import DialogContent from '@material-ui/core/DialogContent';

import Webcam from 'react-webcam';
import Lottie from 'react-lottie';
import { isMobile } from 'react-device-detect';
import axios from 'axios'

const { detect } = require('detect-browser');
const browser = detect();

import * as constants from './constants'
import { defaultConfig, defaultStyles } from './config';

var webcamRef = React.createRef()

class WebcamCapture extends Component {

    constructor(props) {
        super(props)
        
        var animationData = {}
        var label = ""
        var info = ""
        var number = ""
        var overlay = ""
        var mirrored = false
        
        var cameraPosition = constants.camera.FRONT
        if (this.props.documentType === constants.SELFIE) {
            cameraPosition = constants.camera.FRONT
        }
        if (browser.name === "chrome" && browser.os === "Android OS") {
            cameraPosition = constants.camera.FRONT
        }
        
        this.state = {
            config: this.props.config,
            cameraPosition: cameraPosition,
            deviceIdFront: "",
            deviceIdBack: "",
            loading: this.props.loading,
            disableButtons: false,
            showAnimation: false
        };
        
        this.getDeviceId()
    }

    componentWillMount() {
        axios.get(this.state.config.resources.animations.passport)
        .then(response => {
            this.setState({
                animationPassport: response.data
            }, this.forceUpdate())
        })
        .catch((error) => {
            console.log(error)
        })
        axios.get(this.state.config.resources.animations.idfront)
        .then(response => {
            this.setState({
                animationIdFront: response.data
            }, this.forceUpdate())
        })
        .catch((error) => {
            console.log(error)
        })
        axios.get(this.state.config.resources.animations.idback)
        .then(response => {
            this.setState({
                animationIdBack: response.data
            }, this.forceUpdate())
        })
        .catch((error) => {
            console.log(error)
        })
        
        var showAnimation = false
        switch(this.props.documentType) {
          case constants.ID_FRONT:
            showAnimation = true
            break;
          case constants.ID_BACK:
            showAnimation = true
            break;
          case constants.VISA:
            showAnimation = true
            break;
          case constants.PASSPORT:
            showAnimation = true
            break;
          case constants.OTHER:
            showAnimation = false
            break;
          case constants.SELFIE:
            showAnimation = false
            break;
          default:
        }
        this.setState({
            showAnimation: showAnimation
        }, this.forceUpdate())
    }

    componentDidUpdate(prevProps, prevState) {
        if (prevState.disableButtons) {
            this.setState({ disableButtons: false })
        }
        if (prevProps.config != this.props.config) {
            this.setState({
                config: this.props.config
            })
        }
    }

    capture = () => {
        if (this.state.disableButtons) {
            return
        }
        this.setState({
            disableButtons: true
        })

        const image = webcamRef.current.getScreenshot()
        this.props.processImage(image)
    }
    
    getDeviceId = async () => {
        if (browser.name === "chrome" && browser.os === "Android OS") {
            navigator.mediaDevices.enumerateDevices().then((devices) => {
                devices.forEach((device) => {
                    if(device.kind === "videoinput" && device.label.includes("facing front")) {
                        this.setState({
                            deviceIdFront: device.deviceId
                        })
                    }
                    if(device.kind === "videoinput" && device.label.includes("facing back")) {
                        this.setState({
                            deviceIdBack: device.deviceId
                        })
                    }
                })
            })
        }
    }
    
    getFacingMode = (cameraPosition) => {
        if (cameraPosition === constants.camera.FRONT) {
            return "user"
        } else {
            return "environment"
        }
    }
    
    changeCameraPosition = () => {
        if (browser.name === "chrome" && browser.os === "Android OS") {
            if (webcamRef.current && webcamRef.current.stream && webcamRef.current.stream.getVideoTracks) {
                webcamRef.current.stream.getVideoTracks().map(track => track.stop());
            }
            webcamRef = React.createRef()
        }
        if (cameraPosition === constants.camera.FRONT) {
            this.setState({ cameraPosition: constants.camera.BACK })
        } else if (cameraPosition === constants.camera.BACK) {
            this.setState({ cameraPosition: constants.camera.FRONT })
        }
    }
    
    render() {
        /* configure camera label descriptions */
        switch(this.props.documentType) {
          case constants.ID_FRONT:
            this.label = this.props.config.camera.ui.idFront.scanLabel
            this.info = this.props.config.camera.ui.idFront.infoLabel
            this.number = this.props.config.camera.ui.idFront.scanNumber
            this.overlay = constants.OVERLAY_DOCUMENT
            this.animationData = this.state.animationIdFront
            this.mirrored = false
            break;
          case constants.ID_BACK:
            this.label = this.props.config.camera.ui.idBack.scanLabel
            this.info = this.props.config.camera.ui.idBack.infoLabel
            this.number = this.props.config.camera.ui.idBack.scanNumber
            this.overlay = constants.OVERLAY_DOCUMENT
            this.animationData = this.state.animationIdBack
            this.mirrored = false
            break;
          case constants.VISA:
            this.label = this.props.config.camera.ui.visa.scanLabel
            this.info = this.props.config.camera.ui.visa.infoLabel
            this.number = this.props.config.camera.ui.visa.scanNumber
            this.overlay = constants.OVERLAY_DOCUMENT
            this.animationData = this.state.animationPassport
            this.mirrored = false
            break;
          case constants.PASSPORT:
            this.label = this.props.config.camera.ui.passport.scanLabel
            this.info = this.props.config.camera.ui.passport.infoLabel
            this.number = this.props.config.camera.ui.passport.scanNumber
            this.overlay = constants.OVERLAY_DOCUMENT
            this.animationData = this.state.animationPassport
            this.mirrored = false
            break;
          case constants.OTHER:
            this.label = this.props.config.camera.ui.other.scanLabel
            this.info = this.props.config.camera.ui.other.infoLabel
            this.number = this.props.config.camera.ui.other.scanNumber
            this.overlay = constants.OVERLAY_NONE
            this.mirrored = false
            break;
          case constants.SELFIE:
            this.label = this.props.config.camera.ui.selfie.scanLabel
            this.info = this.props.config.camera.ui.selfie.infoLabel
            this.number = this.props.config.camera.ui.selfie.scanNumber
            this.overlay = constants.OVERLAY_SELFIE
            this.mirrored = true
            break;
          default:
        }
    
        /* configure videoConstraints for webcam */
        var width = 800
        var height = 600
        var fullScreen = false
        var videoConstraints = {
            facingMode: this.getFacingMode(this.state.cameraPosition),
            width: width,
            height: height,
        }
        
        /* configure animation settings */
        var animationWidth = width
        if (isMobile) {
            width = window.innerWidth
            height = window.innerHeight
            fullScreen = true
            animationWidth = width - 100
            if (this.props.documentType === constants.PASSPORT ||
                this.props.documentType === constants.VISA) {
                animationWidth = width - 150
            }
        } else {
            animationWidth = 350
            if (this.props.documentType === constants.PASSPORT ||
                this.props.documentType === constants.VISA) {
                animationWidth = 300
            }
        }
        
        /* configure camera position for webcam */
        if (browser.name === "chrome" && browser.os === "Android OS") {
            if (this.state.cameraPosition === constants.camera.BACK) {
                videoConstraints = {
                  deviceId: this.state.deviceIdBack,
                  width: width,
                  height: height,
                }
            }
        }
        
        /* configure animation settings */
        const defaultOptions = {
          loop: false,
          autoplay: true,
          animationData: this.animationData,
          rendererSettings: {
            preserveAspectRatio: 'xMidYMid slice'
          }
        }
        const eventListeners = [{
            eventName: 'complete',
            callback: () => {
                this.setState({
                    showAnimation: false
                }, this.forceUpdate())
            }
        }]

        return (
            <Dialog
                open={this.props.open}
                onClose={() => { this.props.close() }}
                fullScreen = {true}
                fullWidth={false}
                maxWidth={false}
            >
            
            { /* Video Feed */ }
            <Webcam
                ref={webcamRef}
                width={width}
                height={height}
                audio={false}
                mirrored={this.mirrored}
                screenshotFormat={this.props.config.camera.imageFormat}
                videoConstraints={videoConstraints}
                forceScreenshotSourceSize={true}
                screenshotQuality={1}
                onUserMediaError={(error) => {
                    this.props.showSnackMessage("error", "Loading the camera failed with: " + error)
                    this.setState({ disableButtons: true })
                }}
                style={defaultStyles.videoStream}
            />

            { /* Animation */ }
            { this.state.showAnimation?
              <center>
              <Lottie
                  options={defaultOptions}
                  width={animationWidth}
                  eventListeners={eventListeners}
                  style={defaultStyles.lottie}
              />
              </center> : <div></div>
            }

            { /* Loading */ }
            { this.state.loading?
                <center>
                <CircularProgress
                    color="secondary"
                    style={{ position: 'absolute', marginTop: (window.innerHeight / 2) }} />
                </center>
                : <div></div>
            }
            
            { /* Camera Labels */ }
            <div style={defaultStyles.cameraLabels}>
            <center>
            <table>
            <tbody>
            <tr>
                <td>
                    <center>
                    <h1 style={defaultStyles.label} > { this.label } </h1>
                    </center>
                </td>
            </tr>
            <tr>
                <td>
                    <center>
                    <p style={defaultStyles.info} > { this.info } </p>
                    </center>
                </td>
            </tr>
            <tr>
                <td>
                    <center>
                    <p style={defaultStyles.scan} > { this.number } </p>
                    </center>
                </td>
            </tr>
            </tbody>
            </table>
            </center>
            </div>
            
            { /* Camera and Rotate Camera Buttons */ }
            <div>
            <center>
            <table>
            <tbody>
            <tr>
                <td>
                    <Fab
                        color="primary"
                        style={defaultStyles.camera}
                        onClick={() => { this.capture() }}>
                        { this.state.disableButtons ?
                        <CircularProgress
                            style={defaultStyles.progress}
                            disableShrink={true}
                            variant="indeterminate"
                        /> :
                        <RadioButtonUncheckedIcon
                            style={defaultStyles.cameraIcon}
                        />
                        }
                    </Fab>
                </td>
                <td>
                    <Fab
                        color="primary"
                        style={defaultStyles.refresh}
                        onClick={ () => { this.changeCameraPosition() } } >
                        <LoopIcon />
                    </Fab>
                </td>
            </tr>
            </tbody>
            </table>
            </center>
            </div>
            
          </Dialog>
        );
      }
}

export default WebcamCapture;
