import React from 'react';
import superagent from 'superagent';
import _ from 'lodash';

import { fromUnixTime, formatDistanceToNow, set, setDay, addHours, addDays, getUnixTime } from "date-fns";
import { formatInTimeZone } from 'date-fns-tz';

import { DateInput } from 'semantic-ui-calendar-react';

import constants from '../CloudApi/Constants.js';
import WaxIdBitField from './WaxIdBitField.jsx';
import ToolPathDownloadButton from './ToolPathDownloadButton.jsx';
import JobsList from "./JobsList.jsx";
import * as ApiUtils from '../CloudApi/ApiUtils.js';

import { Segment, Modal, Header, Icon, Button, Table, Form, Divider, Label, Popup, Pagination } from 'semantic-ui-react'
import FabricatorWrapper from './FabricatorWrapper.jsx';

const TIMEZONE_LOS_ANGELES = "America/Los_Angeles";

export default class FabricatorHome extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            currentPageIndex: 1,
            pageCount: 0,
            items: [],
            query: {
                origin:"Shopify"
            },
            limit: 50,
            offset: 0,
            count: 0,
            searchBits: _.range(0, 20).map(i => "0")
        };
    }

    async componentDidMount() {
        try {
            let schemas = await ApiUtils.getFabricatorSchemas();
            this.setState({ schemas });

            const params = new URLSearchParams(window.location.search);
            const query = {};
            for (const [key, value] of params.entries()) {
                if (key === "limit") {
                    this.setState({ limit: value });
                } else if (key === "offset") {
                    this.setState({ offset: value });
                } else if (key === "minCreatedAt") {
                    query["minCreatedAt"] = parseInt(value);
                } else if (key === "maxCreatedAt") {
                    query["maxCreatedAt"] = parseInt(value);
                } else {
                    query[key] = value;
                }
            }
            console.log(query);
            this.setState({ query });

            await this.onUpdateQuery();
        } catch (e) {
            console.log(e);
        }
    }

    getUrlSearchParams() {
        const queryString = new URLSearchParams();
        queryString.append("limit", this.state.limit);
        queryString.append("offset", this.state.offset);
        if (this.state.query) {
            for (const [key, value] of Object.entries(this.state.query)) {
                if (value === "" || value === null) continue;
                queryString.append(key, value);
            }
        }

        return queryString;
    }

    onChange(e, { name, value }) {
        const query = this.state.query;

        if (name) {
            console.log("onChange", name, value)

            if (value === "" || value === null) {
                console.log("delete", name, value);
                delete query[name];
            } else {
                if (name === "jobState" && value === ApiUtils.ANY_VALUE) {
                    delete query["jobState"];
                } else if (name === "minCreatedAt") {
                    query["minCreatedAt"] = new Date(value).getTime();
                } else if (name === "maxCreatedAt" && !_.isEmpty(value)) {
                    query["maxCreatedAt"] = new Date(value).getTime();
                } else {
                    query[name] = value;
                }
            }
        }

        console.log(query);

        this.setState({ query }, async () => {
            const params = this.getUrlSearchParams();
            const newPathQuery = `${window.location.pathname}?${params.toString()}`;
            window.history.pushState(null, '', newPathQuery);
            await this.onUpdateQuery();
        });
    }

    onClearValue(e, { name, value }) {
        const query = this.state.query;
        query[name] = "";
        this.setState({ query }, this.onChange(null, {}));
    }

    async onUpdateQuery() {
        try {
            this.setState({ loading: true });
            const params = this.getUrlSearchParams();
            console.log(params.toString());
            const res = await superagent.get(`/api/admin/fabricator/jobs?${params.toString()}`);
            const pageCount = Math.ceil(res.body.count / this.state.limit);
            this.setState({ items: res.body.items, count: res.body.count, pageCount });
        } catch (e) {
            console.log(e);
            this.setState({ error: e });
        }
        this.setState({ loading: false });
    }

    // newPageIndex is 1-based
    async onPageChanged(newPageIndex) {
        this.setState({ currentPageIndex: newPageIndex, offset: Math.max(newPageIndex - 1, 0) * this.state.limit }, () => {
            this.onUpdateQuery(0);
        });
    }

    async handleBitClick(bit) {
        const searchBits = this.state.searchBits;
        searchBits[bit] = (searchBits[bit] === "1") ? "0" : "1";
        this.setState({searchBits});
        let searchBitsTemp = [...searchBits];
        searchBitsTemp[0] = "0";
        let value = parseInt(searchBitsTemp.join(""), 2).toString(16).padStart(5, '0').toUpperCase();
        await this.onChange(null, { name: "waxId", value });
    }

    async onClearWaxId() {
        const query = this.state.query;
        query["waxId"] = "";
        this.setState({ query }, this.onChange(null, {}));
    }

    renderWaxIdSearch() {
        const searchBits = this.state.searchBits;
        const getWaxIdControls = (from, to) => {
            return searchBits.slice(from, to).map((bit, i) => {
                return bit === "1" ? (<span style={{cursor: 'pointer'}} onClick={() => this.handleBitClick(i + from)}>⚫</span>) : (<span style={{cursor: 'pointer'}} onClick={() => this.handleBitClick(i + from)}>🔵</span>);
            });
        }

        if (searchBits.length === 20) {
            let bitFieldLeft = null;
            let bitFieldRight = null;
            bitFieldLeft = 
                <div>
                    {getWaxIdControls(0, 5)}<br />
                    {getWaxIdControls(5, 10)}
                </div>;
            bitFieldRight =
                <div>
                    {getWaxIdControls(10, 15)}<br />
                    {getWaxIdControls(15, 20)}
                </div>;
            return (
                <>
                    <Table inverted color="blue" size='large'>
                        <Table.Header>
                            <Table.Row>
                                <Table.HeaderCell collapsing>Left Eye</Table.HeaderCell>
                                <Table.HeaderCell collapsing>Right Eye</Table.HeaderCell>
                            </Table.Row>
                        </Table.Header>
                        <Table.Row disabled={false}>
                            <Table.Cell collapsing>{bitFieldLeft}</Table.Cell>
                            <Table.Cell collapsing>{bitFieldRight}</Table.Cell>
                        </Table.Row>
                    </Table>
                </>
            );
        } else {
            return null;
        }
    }

    render() {
        if (!this.state.schemas) {
            return <div />;
        }
        
        const pagination = (
            <div style={{ display: "flex", alignItems: "center" }}>
                <div style={{ flex: 0 }}>
                    <Pagination disabled={this.state.count <= 1} activePage={this.state.currentPageIndex} onPageChange={async (e, { activePage }) => this.onPageChanged(activePage)} totalPages={this.state.pageCount} firstItem lastItem />
                </div>
                <div style={{ flex: 1, textAlign: "left", alignItems: "center", marginLeft: "1em" }}>
                    {this.state.items && <p>{this.state.count} items found</p>}
                </div>
            </div>
        );

        return (
            <FabricatorWrapper title="Jobs">
                <Segment secondary>
                    <Form autoComplete={false}>
                        <Form.Group>
                            <DateInput name="minCreatedAt"
                                width={2}
                                autoComplete="off"
                                dateFormat='LL'
                                clearable
                                closable
                                placeholder="Created After"
                                value={new Date(this.state.query.minCreatedAt)}
                                iconPosition="left"
                                onChange={this.onChange.bind(this)} />
                            <DateInput name="maxCreatedAt"
                                width={2}
                                autoComplete="off" 
                                dateFormat='LL'
                                clearable
                                closable
                                placeholder="Create Before"
                                value={new Date(this.state.query.maxCreatedAt)}
                                iconPosition="left"
                                onChange={this.onChange.bind(this)} />
                        </Form.Group>
                        <Form.Group>
                            <Form.Input
                                inline
                                label='Name'
                                name="name"
                                icon={
                                    this.state.query.name && <Icon name="delete" link onClick={this.onClearValue.bind(this, null, { name: "name", value: null })} />
                                }
                                value={this.state.query.name}
                                onChange={this.onChange.bind(this)}
                            />
                            <Form.Select
                                inline
                                size="tiny"
                                label='Status'
                                name="jobState"
                                clearable
                                value={this.state.query.jobState}
                                options={this.state.schemas.JobStateOptions}
                                onChange={this.onChange.bind(this)}
                            />
                            <Form.Select
                                inline
                                label='IPD'
                                name="ipd"
                                clearable
                                value={this.state.query.ipd}
                                options={this.state.schemas.IpdOptions}
                                onChange={this.onChange.bind(this)}
                            />
                            <Popup hideOnScroll on="click" trigger={
                                <Form.Input
                                    inline
                                    label='waxId'
                                    name="waxId"
                                    value={this.state.query.waxId}
                                    autoComplete="off"
                                    icon={
                                        this.state.query.waxId && <Icon name="delete" link onClick={this.onClearValue.bind(this, null, { name: "waxId", value: "" })} />
                                    }
                                    onChange={this.onChange.bind(this)} 
                                />}>
                                <Popup.Content>
                                    {this.renderWaxIdSearch()}
                                </Popup.Content>
                            </Popup>
                        </Form.Group>
                    </Form>
                    <small>Timezone: {TIMEZONE_LOS_ANGELES} (PST/PDT)</small>
                </Segment>
                
                {!this.state.loading && this.state.count > 0 && pagination}
                {this.state.count > 0 && <JobsList jobs={this.state.items} count={this.state.count} loading={this.state.loading} />}
                {this.state.loading && <Segment basic loading={this.state.loading} />}
                {!this.state.loading && this.state.count === 0 && <div>Nothing found.</div>}
                {!this.state.loading && this.state.count > 0 && pagination}
            </FabricatorWrapper>
        );
    }
}
