import React, {Component} from 'react';

import {Button, Col, Icon, Modal, Pagination, Row, Spin, Input} from 'antd';
import './index.css';
import {Mutation, Query} from "react-apollo";
import gql from "graphql-tag";
import {
    DELETE_SCHEMA,
    SHOW_SCHEMA,
    SHOW_TABLE,
    UPDATE_SCHEMA,
    UPDATE_SCHEMA_NAME,
    SEARCH_SCHEMA,
    ADD_SCHEMA
} from '../../../../gql'
import Table from "./Table";
import {request} from 'graphql-request'
import {getCookie} from "../../../../cookie";
import {idGen} from "../../../../func";

const confirm = Modal.confirm;
const Search = Input.Search;


class Schema extends Component {
    constructor(props) {
        super(props);
        this.state = {
            currentTable: props.location.state === undefined ? '' : props.location.state.create ? 'add' : '',
            // default schemaID and schemaName
            schemaID: props.location.state === undefined ? props.schemaID : props.location.state.schemaID,
            schemaName: props.location.state === undefined ? props.schemaName : props.location.state.schemaName,
            editSchemaName: '',
            allData: '',
            data: '',
            page: '1',
            pageSize: '15',
            once: 0
        };
    }

    shouldComponentUpdate(nextProps,nextState) {
        return true;
    }

    switchTable = (table) => {
        this.setState({
            currentTable: table
        })
    };

    changeEditSchemaName = (e) => {
        this.setState({
            editSchemaName: e.target.value
        })
    };

    clearEditSchemaName = () => {
        this.setState({
            editSchemaName: ''
        })
    };

    findColumns = data => this.state.currentTable === '' ? [] : data.find(table => table.name === this.state.currentTable) ? data.find(table => table.name === this.state.currentTable).cols : [];

    findRemark = data => this.state.currentTable === '' ? '' : data.find(table => table.name === this.state.currentTable) ? data.find(table => table.name === this.state.currentTable).remark : '';

    goBack = () => {
        this.setState({
            currentTable: ''
        })
    };

    showTablePagination = (page, pageSize, data) => {
        // console.log(page);
        // console.log(pageSize);
        // console.log(data);
        // 这个之所以这么麻烦，是因为 'apollo 不能存数据' 而 '分页又得用数据展示'，
        // 所以展示 table 的时候分了两个，
        // 首先进入展示 15个 , 这前 15 个没有任何问题。
        // 如果数据多于 15个，在按下第二页的时候 将数据通过 antd 的分页组件的回调函数传入 state，之后 table 的展示由 this.state.data 来接管
        // 但是这又引起一个问题，通过 this.state.data 的展示如果进行删除，是不会通过 apollo 的，这也意味着数据库被删除了，而页面还存在
        // 于是，在使用 this.state.data 的页面的 deleteTableButton 组件内调用该函数，重新刷新 this.state.data
        this.setState({
            page,
            pageSize,
            allData: data,
            data: data.slice((page - 1) * pageSize, page * pageSize)
        });
    };

    fetchData = (referenceID) => {
        let schemaData;
        if (localStorage.getItem('ecommerce') && localStorage.getItem('bills') && localStorage.getItem('subscribe')) {
            switch (referenceID) {
                case 'ecommerce_schemaID':
                    schemaData = localStorage.getItem('ecommerce');
                    break;
                case 'bills_schemaID':
                    schemaData = localStorage.getItem('bills');
                    break;
                case 'subscribe_schemaID':
                    schemaData = localStorage.getItem('subscribe');
                    break;
                default:
                    schemaData = ''
            }
            return Promise.resolve(schemaData);
        } else {
            return new Promise((resolve, reject) => {
                request('http://123.206.193.98:3000/graphql', SEARCH_SCHEMA, {id: referenceID}).then(
                    data => {
                        console.log(data);
                        if (data.schema_by_id !== null) {
                            localStorage.setItem('ecommerce', data.caseSchema.find(obj=>obj.schemaName==='ecommerce').schemaData);
                            localStorage.setItem('subscribe', data.caseSchema.find(obj=>obj.schemaName==='subscribe').schemaData);
                            localStorage.setItem('bills', data.caseSchema.find(obj=>obj.schemaName==='bills').schemaData);
                            resolve(data.schema_by_id.schemaData);
                        }
                    }
                )
            });

        }
    };

    receiveDataFromTable = (data) => {
      this.setState({
          data
      })
    };

    componentWillReceiveProps(next) {
        this.setState({
            currentTable: next.location.state === undefined ? '' : next.location.state.create ? 'add' : '',
            schemaID: next.schemaID,
            schemaName: next.schemaName,
            data: '',
            once: 0
        });
    }

    render() {
        let userID = this.props.userID;
        let trialcase = this.props.trialcase;
        return (
            <Query query={gql(SHOW_TABLE)} variables={{schema_id: this.state.schemaID}}>

                {
                    ({loading, error, data}) => {
                        if (loading) {
                            return <Spin style={{marginLeft: 3}}/>
                        }
                        if (error) {
                            return 'error!';
                        }

                        // let schemaName = data.schema_by_id.schemaName;

                        let copy;
                        if(this.props.location.state)
                            copy = this.props.location.state.copy;

                        // 找到 copy 一定几率不显示的 问题原因，异步导致的未存先取
                        if (data.schema_by_id === null && copy!==true) data = [];
                        else {
                            let reference = data.schema_by_id ? data.schema_by_id.reference : this.props.location.state.reference;
                            data = data.schema_by_id ? JSON.parse(data.schema_by_id.schemaData) : [];
                            if (data.length === 0 && reference !== '' && this.state.once === 0) {
                                this.fetchData(reference).then((data) => {
                                    // 会执行好多好多次
                                    this.setState({
                                        data: JSON.parse(data),
                                        once: 1
                                    })
                                });

                            }

                        }

                        return (
                            <div>
                                {
                                    this.state.currentTable === '' ?
                                        <div>
                                            {
                                                this.state.editSchemaName ?
                                                    <ModifySchemaNameInput
                                                        editSchemaName={this.state.editSchemaName}
                                                        changeEditSchemaName={this.changeEditSchemaName}
                                                        clearEditSchemaName={this.clearEditSchemaName}
                                                        schemaID={this.state.schemaID}
                                                        userID={userID}
                                                        schemaName={this.state.schemaName}
                                                        history={this.props.history}
                                                    />
                                                    :
                                                    <div className={'schema'}>
                                                        <span className={'schema-name'}>{this.state.schemaName}</span>
                                                        {
                                                            trialcase ?
                                                                ''
                                                                :
                                                                <Icon style={{marginLeft: 15}}
                                                                      type="edit"
                                                                      theme="twoTone"
                                                                      onClick={
                                                                          () => {
                                                                              this.setState({editSchemaName: this.state.schemaName})
                                                                          }
                                                                      }
                                                                />
                                                        }
                                                    </div>
                                            }

                                            <div className={'schema-table-list-title'}>
                                                <Row>
                                                    <Col span={10}><span
                                                        className={'schema-table-title'}>Name</span></Col>
                                                    <Col span={10}><span
                                                        className={'schema-table-title'}>Remark</span></Col>
                                                    <Col span={2} offset={2}>
                                                        {
                                                            trialcase ?
                                                                ''
                                                                :
                                                                <span
                                                                    className={'schema-table-title'}
                                                                    onClick={() => {
                                                                        this.setState({
                                                                            currentTable: 'add'
                                                                        })
                                                                    }}>
                                                                    <Icon type="plus"/>
                                                                </span>
                                                        }

                                                    </Col>
                                                </Row>
                                            </div>
                                            <div>
                                                {
                                                    this.state.data ?
                                                        this.state.data.map(table => (
                                                            <div key={table.name}
                                                                 className={'schema-table-list-content'}>
                                                                <Row>
                                                                    <Col
                                                                        span={10}
                                                                        onClick={() => this.switchTable(table.name)}
                                                                    >
                                                                        <span
                                                                            className={'schema-table-content name'}>{table.name}</span>
                                                                    </Col>
                                                                    <Col span={10}>
                                                                        <span
                                                                            className={'schema-table-content'}>{table.remark}</span>
                                                                    </Col>
                                                                    <Col span={2} offset={2}>

                                                                        <span className={'schema-table-content'}>
                                                                            {
                                                                                trialcase ?
                                                                                    ''
                                                                                    :
                                                                                    <DeleteTableButton
                                                                                        currentTable={table.name}
                                                                                        schemaData={data}
                                                                                        schemaID={this.state.schemaID}
                                                                                        userID={userID}
                                                                                        showTablePagination={this.showTablePagination}
                                                                                        page={this.state.page}
                                                                                        pageSize={this.state.pageSize}
                                                                                        fetchData={this.fetchData}
                                                                                        location={this.props.location}
                                                                                    />
                                                                            }

                                                                        </span>
                                                                    </Col>
                                                                </Row>
                                                            </div>
                                                        ))
                                                        :
                                                        data.slice(0, 15).map(table => (
                                                            <div key={table.name}
                                                                 className={'schema-table-list-content'}>
                                                                <Row>
                                                                    <Col
                                                                        span={10}
                                                                        onClick={() => this.switchTable(table.name)}
                                                                    >
                                                                <span
                                                                    className={'schema-table-content name'}>{table.name}</span>
                                                                    </Col>
                                                                    <Col span={10}>
                                                                <span
                                                                    className={'schema-table-content'}>{table.remark}</span>
                                                                    </Col>
                                                                    <Col span={2} offset={2}>
                                                                <span className={'schema-table-content'}>
                                                                    {
                                                                        trialcase ?
                                                                            ''
                                                                            :
                                                                            <DeleteTableButton
                                                                                currentTable={table.name}
                                                                                schemaData={data}
                                                                                schemaID={this.state.schemaID}
                                                                                showTablePagination={this.showTablePagination}
                                                                                page={this.state.page}
                                                                                pageSize={this.state.pageSize}
                                                                                userID={userID}
                                                                                fetchData={this.fetchData}
                                                                                location={this.props.location}
                                                                            />
                                                                    }
                                                                </span>
                                                                    </Col>
                                                                </Row>
                                                            </div>
                                                        ))
                                                }
                                            </div>

                                            <div className={'schema-bottom'}>
                                                <Row>
                                                    <Col span={4}>
                                                        {
                                                            trialcase ?
                                                                <div className={'delete-schema'}>
                                                                    <CopySchemaButton
                                                                        userID={userID}
                                                                        history={this.props.history}
                                                                        schemaName={this.state.schemaName}
                                                                    />
                                                                </div>
                                                                :
                                                                <div className={'delete-schema'}>
                                                                    <DeleteSchemaButton
                                                                        userID={userID}
                                                                        schemaName={this.state.schemaName}
                                                                        history={this.props.history}
                                                                    />
                                                                </div>
                                                        }
                                                    </Col>
                                                    <Col span={4} offset={16}>
                                                        <div className={'pagination'}>
                                                            <Pagination
                                                                simple
                                                                defaultCurrent={1}
                                                                hideOnSinglePage={true}
                                                                defaultPageSize={15}
                                                                total={data.length}
                                                                onChange={(page, pageSize) => {
                                                                    this.showTablePagination(page, pageSize, data)
                                                                }}
                                                            />
                                                        </div>
                                                    </Col>
                                                </Row>
                                            </div>
                                        </div>
                                        :
                                        this.state.currentTable === 'add' ?
                                            <Table
                                                currentTable={''}
                                                schemaData={data}
                                                columns={[]}
                                                remark=''
                                                schemaID={this.state.schemaID}
                                                schemaName={this.state.schemaName}
                                                userID={userID}
                                                goBack={this.goBack}
                                                trialcase={trialcase}
                                                fetchData={this.fetchData}
                                                showTablePagination={this.showTablePagination}
                                                page={this.state.page}
                                                pageSize={this.state.pageSize}
                                                history={this.props.history}
                                                add={'add'}
                                            /> :
                                            <Table
                                                currentTable={this.state.currentTable}
                                                schemaData={data}
                                                columns={this.findColumns(data.length !== 0? data : this.state.data)}
                                                remark={this.findRemark(data.length !== 0? data : this.state.data)}
                                                schemaID={this.state.schemaID}
                                                schemaName={this.state.schemaName}
                                                userID={userID}
                                                goBack={this.goBack}
                                                trialcase={trialcase}
                                                fetchData={this.fetchData}
                                                showTablePagination={this.showTablePagination}
                                                page={this.state.page}
                                                pageSize={this.state.pageSize}
                                                history={this.props.history}
                                                add={'whatever but not add'}
                                            />
                                }

                            </div>
                        );
                    }
                }
            </Query>

        )
    }
}

export default Schema;

class CopySchemaButton extends Component {
    constructor(props) {
        super(props);
        this.state = {
            schemaName: '',
            schemaID: '',
        };
    }

    render() {
        let userID = getCookie('user_id');
        let {history, schemaName} = this.props;
        let schemaID = schemaName + '_schemaID';
        return (
            <div>
                <Mutation
                    mutation={gql(ADD_SCHEMA)}
                    refetchQueries={[{query: gql(SHOW_SCHEMA), variables: {user_id: userID}}]}
                >
                    {(create_schema, {loading, error}) => {
                        if (loading)
                            return <Spin style={{marginLeft: 30, marginTop: 10}}/>;
                        if (error)
                            return 'error';

                        let varObj = {
                            id: idGen('schema'),
                            user_id: userID,
                            createdAt: new Date().getTime(),
                            updatedAt: '',
                            schemaState: 'copy',
                            schemaData: JSON.stringify([]),
                            reference: schemaID,
                            schemaName: schemaName + '_' + Math.random().toString().slice(-3) + Math.random().toString().slice(-4)
                        };

                        return (
                            <Button
                                type="primary"
                                onClick={() => {
                                    create_schema({variables: varObj});
                                    history.push({
                                        pathname: `/graphql-service/my-create/${varObj.schemaName}`,
                                        state: {
                                            schemaName: varObj.schemaName,
                                            schemaID: varObj.id,
                                            copy: true,
                                            reference: varObj.reference
                                        }
                                    });
                                }}

                            >copy</Button>
                        )
                    }}
                </Mutation>
            </div>
        )
    }
}

class DeleteSchemaButton extends Component {
    constructor(props) {
        super(props);
        this.state = {
            schemaName: props.schemaName
        }
    }

    showConfirm = (delete_schema, schemaName, userID) => {
        let _this = this;
        confirm({
            title: 'Do you want to delete this schema?',
            content: 'It cannot be found back!',
            onOk() {
                delete_schema({variables: {schemaName, user_id: userID}});
                _this.props.history.push({
                    pathname: '/graphql-service',
                });
            },
            onCancel() {
            },
        });
    };

    render() {
        let userID = this.props.userID;
        let schemaName = this.props.schemaName;
        return (
            <Mutation
                mutation={gql(DELETE_SCHEMA)}
                update={(cache) => {
                    let data = cache.readQuery({query: gql(SHOW_SCHEMA), variables: {user_id: userID}});

                    data.schema_by_props.splice(data.schema_by_props.findIndex(obj => obj.schemaName === this.state.schemaName), 1);
                    cache.writeQuery({
                        query: gql(SHOW_SCHEMA),
                        variables: {user_id: userID},
                        data
                    });
                }}
            >
                {(delete_schema, {loading, error}) => {
                    if (error)
                        return 'error';
                    if (loading)
                        return <Spin style={{marginLeft: 3}}/>;
                    return (
                        <Button
                            type="danger"
                            onClick={() => {
                                this.showConfirm(delete_schema, schemaName, userID);
                            }}
                        >
                            delete
                        </Button>
                    )
                }}
            </Mutation>
        )
    }
}

class DeleteTableButton extends Component {
    render() {
        let schemaID = this.props.schemaID;
        let userID = this.props.userID;

        let varobj = {
            id: schemaID,
            updatedAt: new Date().getTime(),
            schemaState: 'updated-delete-table',
        };

        return (
            <Query query={gql(SHOW_TABLE)} variables={{schema_id: schemaID}}>
                {
                    ({loading, error, data}) => {
                        if (loading)
                            return <Spin style={{marginLeft: 30, marginTop: 10}}/>;
                        if (error)
                            return 'error';

                        let schemaData = data;
                        let referenceID = data.schema_by_id ? data.schema_by_id.reference : this.props.location.state.reference;

                        return (
                            <Mutation
                                mutation={gql(UPDATE_SCHEMA)}
                                refetchQueries={[{query: gql(SHOW_TABLE), variables: {schema_id: schemaID}}]}
                            >
                                {(update_schema, {loading, error}) => {
                                    if (loading)
                                        return <Spin style={{marginLeft: 30, marginTop: 10}}/>;
                                    if (error)
                                        return 'error';

                                    // 先 query 再 mutation，然后删除
                                    let schemaCols;
                                    if (schemaData.schema_by_id === null) schemaCols = [];
                                    else schemaCols = JSON.parse(schemaData.schema_by_id.schemaData);

                                    const index = this.props.schemaData.findIndex(obj => obj.name === this.props.currentTable);
                                    if (index === -1) {
                                        // 先取数据，然后删除，然后填充
                                        this.props.fetchData(referenceID).then(value => {
                                            schemaCols = JSON.parse(value);
                                            const index = schemaCols.findIndex(obj => obj.name === this.props.currentTable);
                                            schemaCols.splice(index, 1);
                                        });
                                    } else {
                                        schemaCols.splice(index, 1);
                                    }

                                    return (
                                        <Icon type="delete"
                                              onClick={() => {
                                                  update_schema({
                                                      variables: {
                                                          ...varobj,
                                                          schemaData: JSON.stringify(schemaCols)
                                                      }
                                                  });
                                                  this.props.showTablePagination(this.props.page, this.props.pageSize, schemaCols)
                                              }}>

                                        </Icon>
                                    )
                                }}
                            </Mutation>
                        )
                    }
                }

            </Query>


        )
    }
}

class ModifySchemaNameInput extends Component {
    constructor(props) {
        super(props);
        this.state = {}
    }

    render() {
        let userID = this.props.userID;
        let schemaName = this.props.schemaName;
        return (
            <Mutation mutation={gql(UPDATE_SCHEMA_NAME)}>
                {(update_schema, {loading, error}) => {
                    if (error)
                        return 'error';
                    if (loading)
                        return <Spin style={{marginLeft: 3}}/>;
                    return (
                        <div className={'schema'}>
                            <Search
                                value={this.props.editSchemaName}
                                enterButton="Confirm"
                                style={{width: 500}}
                                size="large"
                                onChange={this.props.changeEditSchemaName}
                                onSearch={value => {
                                    update_schema({
                                        variables: {
                                            id: this.props.schemaID,
                                            schemaName: value,
                                            updateAt: new Date().getTime()
                                        }
                                    });
                                    this.props.history.push({
                                        pathname: `/graphql-service/my-create/${value}`,
                                        state: {
                                            schemaName: value,
                                            schemaID: this.props.schemaID,
                                        }
                                    });
                                    this.props.clearEditSchemaName();
                                }}
                            />
                        </div>
                    )
                }}
            </Mutation>
        )
    }
}