import * as React from 'react';
import { connect } from 'react-redux';
import { ApplicationState } from '../store';
import * as PulpTestsStore from '../store/PulpTests';
import PulpTestForm from '../components/PulpTestForm';
import { GridCellProps } from '@progress/kendo-react-grid';
import { Window } from '@progress/kendo-react-dialogs';
import SPCChart from '../components/SPCChart'
import FilterCard from '../components/FilterCard'
import { v4 as uuidv4 } from 'uuid';
import { systems, PulpTestProps, PulpTest, gridState, Direction, materials, materialgrades, pulpblends } from '../interfaces/common'
import JHDataGrid from '../components/DataGrid';
import { authProvider } from '../store/azuread';
import { Card, CardBody, PanelBar, PanelBarItem } from '@progress/kendo-react-layout';
import { DatePicker } from '@progress/kendo-react-dateinputs';
import { ComboBox } from '@progress/kendo-react-dropdowns';
import * as ss from 'simple-statistics'

class CustomCell extends React.Component<GridCellProps, {}> {
    render() {
        if (this.props.field !== undefined) {
            const value = this.props.dataItem[this.props.field];
            return (
                <td > {(value === null) ? '' : this.props.dataItem[this.props.field].toString()}
                </td>
            );
        }
        else {
            return (
                <td></td>
            )
        }
    }
}

class FetchData extends React.PureComponent<PulpTestProps, gridState> {
    constructor(props: any) {
        super(props)
        const dataState = {
            skip: 0,
            take: 500,
            sort: [{ field: 'sample_taken_on', dir: Direction.DSC }],
            group: []
        }
        this.state = {
            data: this.props.pulptests,
            dataState: dataState,
            currentLocale: { languge: 'en-US', localse: 'en' },
            visibleForm: false,
            visiblePopup: false,
            systems: [],
            material: [],
            newFormSystem: { id: 0, name: "one", subtype: "one" },
            materialgradedropdowndata: [],
            pulpblenddropdowndata: [],
            consistency_oven_dried: false,
            contentHeight: 0,
            contentWidth: 0,
            grid: null,
            gridWidth: 1400,
            pulptest: undefined,
            httpMethod: '',
            consistency_spc: {
                usl: undefined,
                lsl: undefined,
                target: undefined,
                ucl: undefined,
                lcl: undefined,
                stdv: undefined,
                mean: undefined
            },
            freeness_spc: {
                usl: undefined,
                lsl: undefined,
                target: undefined,
                ucl: undefined,
                lcl: undefined,
                stdv: undefined,
                mean: undefined
            },
            token: "",
            reportEndTime: undefined,
            reportStartTime: undefined,
            reportLine: undefined
        }
        this.toggleDialog = this.toggleDialog.bind(this);//bind toggle
        this.closeDialog = this.closeDialog.bind(this);//bind close
        this.readSignalR = this.readSignalR.bind(this);
    }

    async toggleDialog(e: systems, data: any, httpMethod: string) {
        this.setState({
            visibleForm: !this.state.visibleForm,
            newFormSystem: e,
            httpMethod: httpMethod,
        });
        if (httpMethod === "PUT") {
            this.setState({ pulptest: data })
        } else {
            this.setState({ pulptest: {} as PulpTest })
        }
        this.setState({
            token: (await authProvider.getIdToken()).idToken.rawIdToken
        })
    }

    closeDialog() {
        this.setState({
            visiblePopup: false,
        });
        this.props.closeDialog()
    }

    dataStateChange = (event: any) => {
        this.setState({
            data: [...this.props.pulptests],
            dataState: event.data
        })
    }
    public async componentDidMount() {
        this.ensureDataFetched();
        this.ensureInitialDataFetched();
        this.readSignalR();
        var token = (await authProvider.getIdToken()).idToken.rawIdToken;
        this.setState({ token: token })
        let griddy = document.querySelector('.k-grid') as HTMLElement
        let griddyHeader = document.querySelectorAll('.k-grid-header-wrap')
        if (griddy !== null) {
        }

        if (griddyHeader !== null) {
            griddyHeader.forEach(function (header: any, key: number, listobj: any) { header.className = header.className + " jh-header" })
        }
    }

    public setPercentage = (percentage: number) => {
        return Math.round(500 / 100) * percentage;
    }

    public readSignalR() {
        if (this.props.registerSignalR) {
            this.props.registerSignalR(Math.random());
        }
    }

    public render() {
        var form;
        if (this.state.systems.length > 0 && this.props.isLoading === false) {
            form = <PulpTestForm
                isLoading={this.props.isLoading}
                addPulpTest={this.props.addPulpTest}
                addPulpTestToList={this.props.addPulpTestToList}
                pulptest={this.state.pulptest}
                pulptests={this.props.pulptests}
                newpulptest={this.props.newpulptest}
                selectedSystem={this.state.newFormSystem}
                materialGrades={this.state.materialgradedropdowndata}
                pulpBlends={this.state.pulpblenddropdowndata}
                closeDialog={this.closeDialog}
                consistencyOvenDried={this.state.consistency_oven_dried}
                httpMethod={this.state.httpMethod}
                resetStoreState={this.props.resetStoreState}
                visibleReportPopup={false}
                visibleCSVReportPopup={false}
                authToken={this.state.token}
            />

            return (
                <React.Fragment >
                        <div className="row example-wrapper" style={{ paddingTop: "5px", backgroundColor: "#29734E", marginBottom: "5px", color: "white" }}>
                            <div className="col-md-12 col-lg-12 col-sm-12 col-xs-12" style={{ verticalAlign: "center", alignSelf: "center" }}>
                                <h2>Pulp Tests</h2>
                            </div>
                        </div>
                    <div className="row example-wrapper">
                        <div className="col-sm">
                            {this.renderButtons()}
                        </div>
                    </div>
                    <div className="row example-wrapper">
                        <div className="col-sm">
                            <div  >
                                <FilterCard
                                    setFilterParams={this.setFilterParams}
                                    available_systems={this.state.systems}
                                    available_material_grades={this.state.materialgradedropdowndata}
                                    available_pulp_blends={this.state.pulpblenddropdowndata}
                                    storeProps={this.props}
                                />
                            </div>
                            <div>
                                {this.renderExport()}
                            </div>
                            <div>
                                {this.renderPulpCharts()}
                            </div>
                        </div>
                    </div>
                    <div className="row example-wrapper" style={{ marginTop: "10px" }}>
                        <div className="col-xl-12 col-lg-12 col-md-12 col-xs-12 col-sm-12">
                            {this.renderPulpTestsTable()}
                        </div>
                    </div>
                    {this.state.visibleForm &&
                        <Window style={{ position: "fixed" }} onClose={this.closeDialog} stage={"FULLSCREEN"} modal>
                            <div className="row example-wrapper" style={{ paddingTop: "5px", backgroundColor: "#29734E", marginBottom: "5px", color: "white" }}>
                                <div className="col-md-12 col-lg-12 col-sm-12 col-xs-12" style={{ verticalAlign: "center", alignSelf: "center" }}>
                            <h2>TEST FOR {this.state.newFormSystem.name}</h2>
                                </div>
                            </div>
                            {form}
                        </Window>
                    }
                    {this.props.visibleReportPopup &&
                        this.exportCSVFile()}
                </React.Fragment>
            );
        }
        else {
            return <React.Fragment>
                <div className="text-center">
                    <div className="spinner-border" role="status">
                        <span className="sr-only">Loading...</span>
                    </div>
                </div>
            </React.Fragment>
        }
    }

    public setFilterParams() {
    }

    private async ensureDataFetched() {
        let materialData: materials[] = [] as materials[];
        let systemData = [] as systems[];
        let materialgradeData = [] as materialgrades[];
        let pulpblendData = [] as pulpblends[];
        let consistencyOven = false;
        var token = null

        if (authProvider.getLoginInProgress() === false) {
            token = (await authProvider.getIdToken()).idToken.rawIdToken
        }
        if (this.state.systems[0] === undefined) {
            try {
                materialData = await fetch('materials/entities.json', {
                    headers:
                        !token ? { 'Access-Control-Allow-Origin': '*' } : {
                            'Authorization': "Bearer " + token,
                            'Access-Control-Allow-Origin': '*',
                            'Content-Type': 'application/json'
                        }
                })
                    .then((response: Response) => {
                        if (!response.ok) {
                            throw response;
                        } else {
                            return response.json();
                        }
                    })
                    .then((data) => { return [data] })// as materials[]
                this.setState({
                    material: materialData
                })
            } catch (error) {
                console.log(error)
            }
            try {
                systemData = await fetch('systems/entities.json?materialid=2', {
                    headers:
                        !token ? { 'Access-Control-Allow-Origin': '*' } : {
                            'Authorization': "Bearer " + token,
                            'Access-Control-Allow-Origin': '*',
                            'Content-Type': 'application/json'
                        }
                })
                    .then((response: Response) => {
                        if (!response.ok) {
                            throw response;
                        } else {
                            return response.json();
                        }
                    })
                    .then((data) => { return data })
                this.setState({
                    systems: systemData
                })
            } catch (error) {
                console.log(error)
            }
            try {
                materialgradeData = await fetch('material_grades/entities.json?materialid=2', {
                    headers:
                        !token ? { 'Access-Control-Allow-Origin': '*' } : {
                            'Authorization': "Bearer " + token,
                            'Access-Control-Allow-Origin': '*',
                            'Content-Type': 'application/json'
                        }
                })
                    .then((response: Response) => {
                        if (!response.ok) {
                            throw response;
                        } else {
                            return response.json();
                        }
                    })
                    .then((data) => { return data })
                this.setState({
                    materialgradedropdowndata: materialgradeData
                })
            } catch (error) {
                console.log(error)
            }
            try {
                pulpblendData = await fetch( process.env.REACT_APP_PULPBLENDS + 'api/entities.json', {//pulp_blends/entities.json', {
                    headers:
                        !token ? { 'Access-Control-Allow-Origin': '*' } : {
                            'Authorization': "Bearer " + token,
                            'Access-Control-Allow-Origin': '*',
                            'Content-Type': 'application/json'
                        }
                })
                    .then((response: Response) => {
                        if (!response.ok) {
                            throw response;
                        } else {
                            return response.json();
                        }
                    })
                    .then((data) => {
                        data = data.map((pulpblendData: pulpblends) => {
                            pulpblendData.descriptionCombined = pulpblendData.description + ' - ' + pulpblendData.code; return pulpblendData;
                        })
                        return data
                    })
                this.setState({ pulpblenddropdowndata: pulpblendData })
            }
            catch (error) {}
            try {
                consistencyOven = await fetch('preferences/getpreferencesbykey.json?key=consistency_oven_dried', {
                    headers:
                        !token ? { 'Access-Control-Allow-Origin': '*' } : {
                            'Authorization': "Bearer " + token,
                            'no-cors': '*',
                            'Access-Control-Allow-Origin': '*',
                            'Content-Type': 'application/json'
                        }
                })
                    .then((response: Response) => {
                        if (!response.ok) {
                            throw response;
                        } else {
                            return response.json();
                        }
                    })
                    .then((data) => { return JSON.parse(data.treated_value) })
                this.setState({
                    consistency_oven_dried: consistencyOven
                })
            } catch (error) {
                console.log(error)
            }
        }
    }

    private ensureInitialDataFetched() {
        if (this.props.requestPulpTests) {
            this.props.requestPulpTests(Math.random());
        }
    }

    public renderButtons() {
        return (
            this.state.systems.map((e: systems, key: any) =>
                <span style={{ paddingRight: "5px" }}> <button key={uuidv4()} className="btn btn-success" onClick={() => this.toggleDialog(e, {} as PulpTest, "POST")} >{e.name}
                </button>
                </span>
            ));
    }
    public SPCHelperBlock(filteredData: any, systemname: any, processLimitData: any, categoriesData: any, materialGradeData: any, title: string, decimals: number = 2) {
        let spcCode = <React.Fragment></React.Fragment>
        if (filteredData.length > 0 && this.props.pulptest !== undefined) {
            spcCode = (
                <SPCChart
                    data={filteredData}
                    categories={categoriesData}
                    type="card"
                    system={systemname}
                    materialgrades={materialGradeData}
                    title={title}
                    processLimits={processLimitData}
                    decimals={decimals}
                    visibleForm={this.state.visibleForm}
                    toggleDialog={this.toggleDialog}
                    storeDataProps={this.props.pulptests}
                />
            )
        }
        return spcCode
    }

    public renderPulpCharts() {
        if (this.props.pulptests !== undefined) {
            let resultsSystem = [... new Set(this.props.pulptests.map((e: PulpTest) => e.systemname))]
            let filteredData = []
            let categoryData = []
            let materialGradeData = []
            let consistencyChartData = []
            let consistencyProcessLimitData = []
            let freenessChartData = []
            let freenessProcessLimitData = []
            return (
                <React.Fragment>
                    {this.props.pulptests.length > 0 &&
                        <div style={{ display: 'flex', justifyContent: 'space-evenly', marginBottom: "10px" }}>
                            <div className='card-deck' style={{ width: "100%" }}>
                                {resultsSystem.map ((e: string) => {
                                    filteredData = this.props.pulptests.filter((filter: PulpTest) => filter.systemname === e)
                                    categoryData = filteredData.map(datapoint => new Date(datapoint.sample_taken_on).getHours() + ':' + new Date(datapoint.sample_taken_on).getMinutes())
                                    materialGradeData = [...new Set(filteredData.map(dataitem => dataitem.materialgradename))]
                                    consistencyChartData = filteredData.map((data: PulpTest) => { return { materialgradename: data.materialgradename, datavalue: data.consistency, dataextended: data } })
                                    consistencyProcessLimitData = filteredData.map((data: PulpTest) => {
                                        return {
                                            materialgradename: data.materialgradename,
                                            datausl: data.consistency_usl,
                                            datalsl: data.consistency_lsl,
                                            datatarget: data.consistency_target
                                        }
                                    })
                                    freenessChartData = filteredData.map((data: PulpTest) => { return { materialgradename: data.materialgradename, datavalue: data.corrected_freeness, dataextended: data } })
                                    freenessProcessLimitData = filteredData.map((data: PulpTest) => {
                                        return {
                                            materialgradename: data.materialgradename,
                                            datausl: data.freeness_usl,
                                            datalsl: data.freeness_lsl,
                                            datatarget: data.freeness_target
                                        }
                                    })
                                        return (
                                            <React.Fragment key={uuidv4()} >
                                                {this.SPCHelperBlock(consistencyChartData, e, consistencyProcessLimitData, categoryData, materialGradeData, "Consistency")}
                                                {this.SPCHelperBlock(freenessChartData, e, freenessProcessLimitData, categoryData, materialGradeData, "Freeness")}
                                            </React.Fragment>
                                        )
                                    })
                                }
                            </div>
                        </div>
                    }
                </React.Fragment>
            )
        }
    }

    MyCustomCell = (props: any) => <CustomCell {...props} />

    public renderPulpTestsTable() {
        if (this.props.pulptests.length > 0) {
            let gridAllData: PulpTest[] = this.props.pulptests //has all the pulp test data
            let materialgradenames = [...new Set(this.props.pulptests.map((e: PulpTest) => e.materialgradename))]//I should probably do this somewhere else so it can be reused
            let pulpblendcodes = [...new Set(this.props.pulptests.map((e: PulpTest) => e.pulpBlendCode))]//I should probably do this somewhere else so it can be reused
            var GridTables = this.state.systems.map((system: systems, key: any) => {
                let gridAllSystemData = gridAllData.filter((filter: PulpTest) => filter.systemname === system.name)
                let returnGrid = <React.Fragment></React.Fragment>
                if (gridAllSystemData.length > 0) {
                    let mean = undefined;
                    let last24sData = gridAllSystemData.filter((filter: PulpTest) => filter.sample_taken_on > new Date(new Date().getTime() - (24 * 60 * 60 * 1000))).map((filter: PulpTest) => filter.consistency)
                    if (last24sData.length > 0) {
                        mean = ss.mean(last24sData).toFixed(2)
                    }
                    returnGrid = <React.Fragment key={uuidv4()}>
                        <h3 style={{ paddingLeft: "15px", backgroundColor: "#29734E", color: "white" }}>{system.name} - Avg Consistency Last 24 Hours: {mean} </h3>
                        <JHDataGrid
                            pulptests={gridAllSystemData}
                            closeDialog={this.closeDialog}
                            editButton={this.editButton}
                            gridType={system.subtype}
                            renderEditForm={this.renderEditForm}
                            toggleDialog={this.toggleDialog}
                            visibleForm={this.state.visibleForm}
                        />
                    </React.Fragment>
                }
                return returnGrid;
            })
            return (
                <React.Fragment  >
                    {GridTables}
                </React.Fragment>
            );
        } else {
            return (
                <React.Fragment></React.Fragment>
            )
        }
    }

    public editButton = (props: any) => {
        return (
            <td >
                <button className="btn b-edit"
                    value={JSON.stringify(props.dataItem)}
                    onClick={this.renderEditForm.bind(this)}>
                    Edit
                </button>
            </td >
        )
    }

    public renderEditForm(data: any) {
        data = JSON.parse(data.target.value)
        this.toggleDialog(data.system, data, "PUT")
    }

    // Re-usable change handler
    public handleSingleChange = (event: any) => {
        this.setState({
            [event.target.name]: event.target.value
        } as Pick<PulpTest, any>, () => {});
    }

    public renderExport() {
        return (
            <div style={{ display: 'flex', justifyContent: 'space-evenly', marginBottom: "10px" }} >
                <Card style={{ width: "100%" }}>
                    <CardBody style={{ overflow: "auto", padding: 0 }}>
                        <PanelBar>
                            <PanelBarItem title="Export Data">
                                <div style={{ marginLeft: "20px", marginTop: "5px", marginBottom: "5px" }}>
                                    <div className="row example-wrapper" style={{ marginTop: "5px" }}>
                                        <div className="col">
                                            <button className="btn btn-primary" style={{ width: "90%" }} onClick={() => {
                                                if (this.props.loadReportDialog) {
                                                    this.props.loadReportDialog(Date.now())
                                                }
                                            }
                                            }>
                                                CSV
                                            </button>
                                        </div>
                                    </div>
                                </div>
                            </PanelBarItem>
                        </PanelBar>
                    </CardBody>
                </Card>
            </div>
        )
    }

    public exportCSVFile() {
        let window =
            <Window style={{ position: "fixed", marginTop: "-100px", width: "380px", height: "355px", zIndex: "10003" }} title={"REPORT PARAMETERS"} onClose={this.closeDialog} modal >
                <div>
                    <div className="row" style={{ marginTop: "10px" }}>
                        <div className="col-4">
                            START:
                        </div>
                        <div className="col-8">
                            <DatePicker
                                onChange={this.handleSingleChange}
                                name="reportStartTime"
                            />
                        </div>
                    </div>

                    <div className="row" style={{ marginTop: "10px" }}>
                        <div className="col-4">
                            END:
                        </div>
                        <div className="col-8">
                            <DatePicker
                                onChange={this.handleSingleChange}
                                name="reportEndTime"
                            />
                        </div>
                    </div>
                    <div className="row" style={{ marginTop: "10px" }}>
                        <div className="col-4">
                            LINE:
                        </div>
                        <div className="col-8">
                            <ComboBox
                                onChange={this.handleSingleChange}
                                name="reportLine"
                                textField="name"
                                dataItemKey="id"
                                data={this.state.systems}
                            />
                        </div>
                    </div>
                    <div className="row" style={{ marginTop: "10px" }}>
                    </div>
                    <div className="row" style={{ marginTop: "10px" }}>
                        <div className="col-4">
                            <button className="k-primary k-button"
                                onClick={this.download("csv")}
                                style={{ marginLeft: "119px", marginTop: "46px" }}
                            >
                                DOWNLOAD
                            </button>
                        </div>
                    </div>
                </div>
            </Window>
        return (<div>{this.state.visiblePopup && window}</div>)
    }


    public download = (reportType: string = "xlsx") => async (
        event: any
    ): Promise<void> => {
        var data = {
            sample_tested_at_from: new Date(Date.now()),
            sample_tested_at_to: new Date(Date.now()),
            line: "",
            scope: "",
        }

        let apiURL = '/api/entities/'
        if (reportType === "xslx") {
            apiURL = apiURL + 'report'
        } else {
            apiURL = apiURL + 'reportcsv'
        }

        if (this.state.reportStartTime !== undefined && this.state.reportEndTime !== undefined) {
            if (this.state.reportLine !== undefined) {
                apiURL = apiURL + "?sampled_at=" + this.state.reportStartTime.toLocaleDateString() + '..' + this.state.reportEndTime.toLocaleDateString() + '&system_id=' + this.state.reportLine.id;
            } else {
                apiURL = apiURL + "?sampled_at=" + this.state.reportStartTime.toLocaleDateString() + '..' + this.state.reportEndTime.toLocaleDateString()
            }
            window.location.href = apiURL;
            this.closeDialog();
        } else {
            alert("error: parameters are incomplete");
        }
    }
}

export default connect(
    (state: ApplicationState) => state.pulpTests, // Selects which state properties are merged into the component's props
    PulpTestsStore.actionCreators // Selects which action creators are merged into the component's props
)(FetchData as any);
