import React, { useRef } from 'react';
import superagent from 'superagent';
import { Message, Segment, Grid, Header, Icon, Button, Table, Form, Divider, Label, Transition, Image } from 'semantic-ui-react'

export default class HandScannerInput extends React.Component {
    timeout;
    constructor(props) {
        super(props);
        this.state = {
            scannedSerialNumber: props.value || "",
            shiftKeyHeld: false,
            ctrlKeyHeld: false,
            show: false,
            fastStrokes : 0,
        };
    }

    async handleKeyDown(event) {
        if (event.key === "Control") {
            console.log("Ctrl pressed"); //debug
            this.setState({ ctrlKeyHeld: true });
        }
        else if (event.key === "Shift") {
            console.log("Shift pressed", { shiftState: this.state.shiftKeyHeld }); //debug
            this.setState({ shiftKeyHeld: true });
        }
    }

    async handleKeyUp(event) {
        event.preventDefault();
        let fastStrokes = this.state.fastStrokes + 1;

        if (event.key === "Control") {
            console.log("Ctrl released");
            this.setState({ ctrlKeyHeld: false });
        } else if (event.key === "Shift") {
            //Nixed as the scanner releases shift before the triggering the shifted keypress
            // console.log("Shift released", {shiftState: this.state.shiftKeyHeld}); //debug
            // this.setState({ shiftKeyHeld: false });
        }
        if (event.target.name && event.target.name !== "scannedSerialNumber") {
            return;
        }

        if (event.key === "Backspace" && event.target.name !== "scannedSerialNumber") {
            let scannedSerialNumber = this.state.scannedSerialNumber;
            this.setState({ scannedSerialNumber: scannedSerialNumber.slice(0, -1) });
        } else if (event.key === " ") {
            let altSn = this.state.altSerialNumber ? this.state.altSerialNumber : "";
            console.log("Space pressed");
            console.log(this.state.scannedSerialNumber + altSn);
            this.setState({ scannedSerialNumber: this.state.scannedSerialNumber + altSn });
        } else {
            let key = "";
            if (event.key.length === 1 && event.target.name !== "scannedSerialNumber" && !this.state.ctrlKeyHeld) {
                key = this.getShiftedKeypress(event);
                this.setState({ shiftKeyHeld: false });
            }
            let scannedSerialNumber = this.state.scannedSerialNumber;
            this.setState({ scannedSerialNumber: scannedSerialNumber + key });
        }
        
        if (this.timeout) {
            // console.log({sn: this.state.scannedSerialNumber}); //debug
            clearTimeout(this.timeout);
        }

        this.setState({ fastStrokes });
        this.strokesTimeout = setTimeout(this.resetFastStrokes.bind(this), 5);
        this.timeout = setTimeout(this.onScanFinished.bind(this, (event.key === "Enter" || event.key === " " || fastStrokes >= 8)), 250);
    }

    async componentDidMount() {
        this.setState({ menuLoading: true });
        document.addEventListener('keyup', this.handleKeyUp.bind(this));
        document.addEventListener('keydown', this.handleKeyDown.bind(this));

        setTimeout(() => {this.setState({ show: true })}, 250);
    }

    async onScanFinished(forceSubmit = true) {
        let scannedSerialNumber = this.state.scannedSerialNumber;

        if (forceSubmit) {
            // HACK HACK HACK
            //
            // The Bigscreen serial numbers are all lowercase.
            if (scannedSerialNumber.startsWith("bs")) {
                scannedSerialNumber = scannedSerialNumber.toUpperCase();
            }

            console.log("Scan finished", scannedSerialNumber); //debug
            await this.props.onScanFinished(scannedSerialNumber);

            this.setState({ scannedSerialNumber: "" });
        }
    }

    onChange(e, { name, value }) {
        this.setState({ [name]: value })
    }

    onSearch(e) {
        if (this.timeout) {
            clearTimeout(this.timeout);
        }
        this.setState({ scannedSerialNumber: this.state.altSerialNumber }, this.onScanFinished.bind(this));
    }

    onIngestInventoryItem(e) {
        e.preventDefault();
    }

    onDismissMessage(e) {
        this.setState({ message: null });
    }

    onClearValue(e, { name, value }) {
        this.setState({ scannedSerialNumber: "" }, this.onScanFinished.bind(this));
    }

    resetFastStrokes() {
        this.setState({ fastStrokes: 0 });
    }

    /*
    * We use this function to get shift-modified input from the scanner. It is specifically needed for input when the textbox is not focused.
    *
    * Reason: event.key always returns the "unshifted" version of the key's name.
    */
    getShiftedKeypress(event) {
        const shiftedKeys = {
            '`': '~',
            '1': '!',
            '2': '@',
            '3': '#',
            '4': '$',
            '5': '%',
            '6': '^',
            '7': '&',
            '8': '*',
            '9': '(',
            '0': ')',
            '-': '_',
            '=': '+',
            '[': '{',
            ']': '}',
            '\\': '|',
            ';': ':',
            "'": '"',
            ',': '<',
            '.': '>',
            '/': '?'
        };
        const shiftKeyHeld = this.state.shiftKeyHeld;
        let retVal = event.key;

        // if(shiftKeyHeld) console.log("getActualKeyPressed()", { shiftState: shiftKeyHeld, key: retVal, shiftedLookup: shiftedKeys[retVal] }); //debug
        
        if (shiftKeyHeld && shiftedKeys[retVal]) {
            console.log("Shifted key:", shiftedKeys[event.key]); //debug
            retVal = shiftedKeys[retVal];
        } else if (shiftKeyHeld && retVal.length === 1 && retVal.match(/[a-zA-Z]/)) {
            console.log("Shifted letter:", retVal.toUpperCase()); //debug
            retVal = retVal.toUpperCase();
        }

        return retVal;
    }

    render() {
        let images = ['/images/scanner.png', '/images/nfc.png'];
        let title = "Scan a barcode";
        let altTitle = "Scan a barcode";
        if (this.props.type === "inventory") {
            title = "Scan a barcode or NFC Tag";
            altTitle = "Enter serial number";
        } else if (this.props.type === "trackingLabel") {
            images = ['/images/sample_label.png'];
            title = "Scan a tracking label";
            altTitle = "Enter a tracking number";
        }

        if (this.props.inlineFormInput) {
            return (
                <Form.Input
                    inline
                    inlineLabel
                    width={4}
                    label={this.props.label || "Scan Serial Number"}
                    placeholder="Scan"
                    name="scannedSerialNumber"
                    icon={
                        this.state.scannedSerialNumber ? <Icon name="delete" link onClick={this.onClearValue.bind(this)} /> : <Icon name="barcode" />
                    }
                    value={this.state.scannedSerialNumber}
                    onChange={this.onChange.bind(this)}
                />
            )
        }

        if (this.props.size === "small") {
            return (
                <div onLoad={() => { this.setState({ show: true })}}>
                    <Transition animation={"bounce"} duration={500} visible={this.state.show}>
                        <Segment>
                            <Image floated='left' size='tiny' src='/images/scanner.png' />
                            <Header as="h2">
                                <Header.Content>
                                Scan a barcode
                                <Header.Subheader>{this.state.scannedSerialNumber}</Header.Subheader>
                                </Header.Content>
                            </Header>
                        </Segment>
                    </Transition>
                </div>
            )
        } else {
            return (
                <div style={{marginBottom: "1em" }}>
                    <Segment raised color="green">
                        <Grid columns={2} >
                            <Grid.Column verticalAlign='middle' textAlign='center'>
                                <Header icon as="h2">
                                    {images.map((image, index) => <Image key={index} size="tiny" src={image} />)}
                                    <Header.Content>
                                    {title}
                                    <Header.Subheader>{this.state.scannedSerialNumber}</Header.Subheader>
                                    </Header.Content>
                                </Header>
                            </Grid.Column>
    
                            <Grid.Column textAlign='center' verticalAlign='middle'>
                                <Segment basic fluid>
                                <Form textAlign='center' fluid loading={this.state.loading} onSubmit={this.onSearch.bind(this)}>
                                    <Form.Group inline>
                                        <Form.Input width={12} icon="search" size='big' required label={altTitle} value={this.state.altSerialNumber} name="altSerialNumber" onChange={this.onChange.bind(this)} />
                                        <Button primary content='Search' type='submit' size='big' />
                                    </Form.Group>
                                </Form>
                                </Segment>
                            </Grid.Column>
                        </Grid>
                        <Divider vertical>Or</Divider>
                    </Segment>
                    {this.state.scannedSerialNumber}
                </div>
            );
        }
        
    }
}
