import { Component } from 'react';
import * as React from 'react';
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
import { AppState } from '../store';
import { connect } from 'react-redux';
import { PLAYER_MODEL_FILENAME } from '../game/player';


interface TalkyFaceProps {
    modalOpen: boolean
}

class TalkyFace extends Component<TalkyFaceProps> {
    camera: THREE.PerspectiveCamera;
    renderer: THREE.WebGLRenderer;
    scene: THREE.Scene;
    mount: HTMLElement;
    animations: THREE.AnimationClip[];
    mixer: THREE.AnimationMixer;
    model: THREE.Group;
    actions: {};
    frameId: number;
    clock: THREE.Clock;

    constructor(props: TalkyFaceProps) {
        super(props);
        this.init()
    }

    init = () => {
        this.camera = new THREE.PerspectiveCamera(55, 1, 1, 3000);
        this.camera.position.set(0, 2, -1);
        this.camera.lookAt(0, 0, -1)
        // this.camera.up.set(0, 0, 1);

        // RENDERER
        this.renderer = new THREE.WebGLRenderer({ antialias: true });
        this.renderer.setPixelRatio(window.devicePixelRatio);
        this.renderer.setSize(200, 200);

        
        this.renderer.shadowMap.enabled = true;

        this.scene = new THREE.Scene();
        this.scene.background = new THREE.Color(0x555555);

        // LIGHTS
        this.scene.add(new THREE.HemisphereLight(0x443333, 0x111122,30));

        let pl = new THREE.PointLight(0xFFFFFFF, 1, 1000);
        pl.position.set(50, -50, 10);
        this.scene.add(pl);

        let pl1 = new THREE.PointLight(0xFFFFFFF, 1, 1000);
        pl1.position.set(-50, 50, 50);
        this.scene.add(pl1);

        // ROBOT MODEL
        this.clock = new THREE.Clock()
        let loader = new GLTFLoader();
        loader.load(PLAYER_MODEL_FILENAME, (gltf) => {
            this.model = gltf.scene;
            this.animations = gltf.animations;
            this.mixer = new THREE.AnimationMixer(this.model)
            this.actions = {};
            for (var i = 0; i < this.animations.length; i++) {
                var clip = this.animations[i];
                var action = this.mixer.clipAction(clip);
                this.actions[clip.name] = action;
                if (clip.name != "Idle") action.repetitions = 1
            }
            // this.actions["Idle"].play()
            this.actions["ThumbsUp"].timeScale = 0.2
            console.log(this.actions["ThumbsUp"])
            this.actions["ThumbsUp"].play();
            this.model.children[0].rotation.x = Math.PI * 0.5;
            this.model.children[0].rotation.y = Math.PI - 0.3;
            this.model.children[0].rotation.z = Math.PI;
            this.model.position.setZ(-0.3)
            this.model.scale.set(0.3, 0.3, 0.3)
            this.scene.add(this.model);
        })

    }

    animate = () => {
        this.frameId = requestAnimationFrame(this.animate);
        var dt = this.clock.getDelta();
        if (this.mixer) this.mixer.update(dt);
        this.renderer.render(this.scene, this.camera);
    }

    startAnimating = () => {
        if (!this.frameId) {
            this.frameId = requestAnimationFrame(this.animate);
        }
    }
    stopAnimating = () => {
        cancelAnimationFrame(this.frameId);
        this.frameId = 0;
        console.log("now talkyface should have stopped rendering")
    }

    componentDidMount() {
        this.mount.appendChild(this.renderer.domElement);
        this.startAnimating();
    }

    compoentWillUnmount() {
        this.stopAnimating()
    }

    componentDidUpdate(prevProps: TalkyFaceProps) {
        if (prevProps.modalOpen && !this.props.modalOpen) this.stopAnimating()
        if (!prevProps.modalOpen && this.props.modalOpen) this.startAnimating()
    }

    render() {
        return (<div
            className="TalkyFace"
            ref={(mount: HTMLElement) => { this.mount = mount }}
            style={{
                width: "200px", height: "200px", display: "block"
            }} />)
    }

}

const mapStateToProps = (state: AppState) => {
    return {
        modalOpen: state.gameScreenState.modalOpen
    }
}

export default connect(mapStateToProps)(TalkyFace);
