import React, { useRef, useEffect } from 'react';
import superagent from 'superagent';
import { fromUnixTime, formatDistanceToNow } from "date-fns";
import { formatInTimeZone } from 'date-fns-tz';
import * as THREE from 'three';
import { STLLoader } from 'three/examples/jsm/loaders/STLLoader';

import * as ApiUtils from '../CloudApi/ApiUtils.js';
import constants, { DEFAULT_TIMEZONE } from '../CloudApi/Constants.js';
import WaxIdBitField from './WaxIdBitField.jsx';
import ToolPathDownloadButton from './ToolPathDownloadButton.jsx';

import { Header, Message, Icon, Button, Table, Label, Modal } from 'semantic-ui-react'

const MeshViewer = (props) => {
    const { scanFileMeshBuffer } = props;
    const containerRef = useRef(null);

    useEffect(() => {
        const renderer = new THREE.WebGLRenderer({ antialias: true });

        const width = containerRef.current.offsetWidth;
        const height = 1000;

        renderer.setSize(width, height);
        containerRef.current.appendChild(renderer.domElement);

        const scene = new THREE.Scene();
        scene.background = new THREE.Color(0xffffff);
        const camera = new THREE.PerspectiveCamera( 90, containerRef.current.offsetWidth / 1000, 0.1, 1000);

        // Lighting setup
        const light = new THREE.AmbientLight(0xffffff);
        scene.add(light);

        // Load STL file
        const loader = new STLLoader();
        const geometry = loader.parse(scanFileMeshBuffer);
        const material = new THREE.MeshStandardMaterial({ wireframe: true, color: 0xaaaaaa });
        const mesh = new THREE.Mesh(geometry, material);

        camera.position.z = 20;
        camera.lookAt(mesh.position);

        scene.add(mesh);
        
        mesh.position.x -= 5;

        // Rotate the mesh by 90 degrees so the face is correctly oriented.
        mesh.rotation.x = Math.PI / 2;

        let t = 0;
        // Animation loop
        const animate = () => {
            requestAnimationFrame(animate);
            renderer.render(scene, camera);
            mesh.rotation.z = Math.sin(t++ / 100);
        };
        animate();

        // Cleanup
        return () => {
            renderer.dispose();
        };
    }, []);
  
    return <div ref={containerRef} style={{ width: '100%', height: '100%' }} />;
};

export default class ScanRequestComponent extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            loading: false,
            revokeScanRequestModalOpen: false,
        };
    }

    async componentDidMount() {
        /*
        const res = await superagent.get(`/api/admin/fabricator/scan_request/${this.props.scanRequest.id}/mesh`).accept("application/json");
        const decodedData = window.atob(res.body.data);
        const arrayBuffer = new ArrayBuffer(decodedData.length);
        const uint8Array = new Uint8Array(arrayBuffer);

        for (let i = 0; i < decodedData.length; i++) {
            uint8Array[i] = decodedData.charCodeAt(i);
        }
        this.setState({ scanFileMeshBuffer: arrayBuffer })
        */
    }

    showRevokeScanRequestModal() {}

    openRevokeScanRequestModal(i, e) {
        this.setState({ revokeScanRequestModalOpen: true});
    }

    closeRevokeScanRequestModal(i, e) {
        this.setState({ revokeScanRequestModalOpen: false});
    }

    async onRevokeScanRequest(e) {
        e.preventDefault();
        this.setState({ loading: true });
        try {
            let res = await superagent.put(`/api/admin/fabricator/scan_request/${this.props.scanRequest.id}`).send({
                scanRequestState: this.props.schemas.ScanRequestStates["Revoked"]
            });
            window.location.reload();
        } catch (e) {
            window.alert("Error sending scan request email: " + e.message);
            console.error(e);
        }

        this.setState({ loading: false, revokeScanRequestModalOpen: false});
    }

    renderScanMesh() {
        return <div />;
        /*
        if (!this.state.scanFileMeshBuffer) {
            return <div />;
        }

        return <MeshViewer scanFileMeshBuffer={this.state.scanFileMeshBuffer} />;
        */
    }

    renderIpdLabel() {
        if (this.props.scanRequest.ipd === -1) {
            return <Label color="orange">IPD Not Set</Label>
        }

        return <Label color="blue">{this.props.scanRequest.ipd}mm</Label>
    }

    render() {
        if (this.state.loading) {
            return (
                <div />
            )
        }

        let createdAtDateTime = fromUnixTime(this.props.scanRequest.createdAt / 1000);
        const createdAt = formatInTimeZone(createdAtDateTime, DEFAULT_TIMEZONE, 'PPPp z');
        const fromNow = formatDistanceToNow(createdAtDateTime, { addSuffix: true });

        const history = this.props.scanRequest.history && this.props.scanRequest.history.map((historyItem, historyItemIndex) => {
            let createdAtDateTime = fromUnixTime(historyItem.createdAt / 1000);
            const createdAt = formatInTimeZone(createdAtDateTime, DEFAULT_TIMEZONE, 'PPPp z');
            return (<Table.Row>
                <Table.Cell width={2}>
                    {createdAt}
                </Table.Cell>
                <Table.Cell width={2}>
                    {historyItem.bigscreenAccountId}
                </Table.Cell>
                <Table.Cell>
                    {historyItem.message}
                    {(historyItem.metaData && historyItem.metaData.reason) && <div><strong>Reason:</strong> {historyItem.metaData.reason}</div>}
                </Table.Cell>
            </Table.Row>)
        });

        const scanRequestState = Object.entries(this.props.schemas.ScanRequestStates).find(entry => entry[1] === this.props.scanRequest.scanRequestState)[0];
        const stateLabelColor = (this.props.scanRequest.scanRequestState === this.props.schemas.ScanRequestStates["VerifiedAndReady"]) ? "green" : "grey";

        const footer = (
            <Table.Footer fullWidth>
                <Table.Row>
                    <Table.HeaderCell colSpan='2'>
                        <Button floated='right' color='red' onClick={this.openRevokeScanRequestModal.bind(this)}><Icon name='trash alternate outline' />Revoke this scan request!</Button>
                    </Table.HeaderCell>
                </Table.Row>
            </Table.Footer>
        );

        return (
            <div>
                <Modal dimmer="inverted" closeOnEscape={true} closeOnDimmerClick={true} closeIcon
                    onClose={this.closeRevokeScanRequestModal.bind(this)}
                    open={this.state.revokeScanRequestModalOpen}>
                    <Header icon='user' content='Revoke this scan request' />
                    <Modal.Content>
                        Are you sure you want to revoke this scan request?
                    </Modal.Content>
                    <Modal.Actions>
                        <Button color='red' loading={this.state.loading} onClick={this.onRevokeScanRequest.bind(this)}>
                            <Icon name='trash alternate outline' />Yes, Revoke This Scan Request
                        </Button>
                    </Modal.Actions>
                </Modal>

                <Table compact singleLine loading={this.state.loading}>
                    <Table.Body>
                        <Table.Row>
                            <Table.HeaderCell width={3}>ID</Table.HeaderCell>
                            <Table.Cell><strong>{this.props.scanRequest.id}</strong>&nbsp;<Button size="tiny" onClick={() => {navigator.clipboard.writeText(this.props.scanRequest.id)}}>Copy</Button></Table.Cell>
                        </Table.Row>

                        <Table.Row>
                            <Table.HeaderCell width={3}>Owner</Table.HeaderCell>
                            <Table.Cell><a href={`/account/${this.props.scanRequest.ownerBigscreenAccountId}`}>View account</a></Table.Cell>
                        </Table.Row>

                        <Table.Row>
                            <Table.HeaderCell width={3}>Created</Table.HeaderCell>
                            <Table.Cell>{createdAt} ({fromNow})</Table.Cell>
                        </Table.Row>

                        <Table.Row>
                            <Table.HeaderCell width={3}>State</Table.HeaderCell>
                            <Table.Cell><Label color={stateLabelColor} horizontal>{scanRequestState}</Label></Table.Cell>
                        </Table.Row>

                        <Table.Row>
                            <Table.HeaderCell width={3}>Version</Table.HeaderCell>
                            <Table.Cell>{this.props.scanRequest.version}</Table.Cell>
                        </Table.Row>

                        <Table.Row>
                            <Table.HeaderCell width={3}>IPD</Table.HeaderCell>
                            <Table.Cell>{this.renderIpdLabel()}</Table.Cell>
                        </Table.Row>

                        <Table.Row>
                            <Table.HeaderCell width={3}>Mesh</Table.HeaderCell>
                            <Table.Cell>{this.renderScanMesh()}</Table.Cell>
                        </Table.Row>

                        {(this.props.scanRequest.jobIds && this.props.scanRequest.jobIds.length > 0) && <Table.Row>
                            <Table.HeaderCell width={3}>Attached Jobs</Table.HeaderCell>
                            <Table.Cell>{this.props.scanRequest.jobIds.map(jobId => <Button inverted color="blue" size="tiny" href={`/fabricator/job/${jobId}`}><Icon name='cog' />Job #{jobId}</Button>)}</Table.Cell>
                        </Table.Row>
                        }
                    </Table.Body>
                    {footer}
                </Table>
                <Table compact celled padded>
                    <Table.Header>
                        <Table.Row>
                            <Table.HeaderCell width={2}>When</Table.HeaderCell>
                            <Table.HeaderCell width={2}>User</Table.HeaderCell>
                            <Table.HeaderCell fluid>Message</Table.HeaderCell>
                        </Table.Row>
                    </Table.Header>
                    <Table.Body>
                        {history}
                    </Table.Body>
                </Table>
            </div>
        )
    }
}
