import React, { Component } from 'react'
import { Form, Button, Table, Tooltip, Drawer } from 'antd'
import { AntIcon } from 'components'
import { cloneDeep, isEqual } from 'lodash'

const propsMap = ['columns', 'autoLoad', 'loadData', 'pageIndex', 'pageSize']

const clearChildren = data => {
    data.forEach(p => {
        if (p.children) {
            if (p.children.length) {
                p.children = clearChildren(p.children)
            } else {
                delete p.children
            }
        }
    })
    return data
}

const rowNoColumn = {
    title: '#',
    dataIndex: 'rowNo',
    width: 30,
    fixed: true,
    align: 'center',
    ellipsis: true,
    className: 'yo-table--row-no',
    render: (text, record, index) => index + 1,
}

/**
 * 渲染查询栏
 * @returns
 */
function renderQueryBar() {
    const { query, moreQuery, onQueryChange, queryInitialValues } = this.props

    return (
        <div className="yo-query-bar">
            <Form
                layout="inline"
                ref={this.queryForm}
                onFinish={value => this.onQuery(value)}
                initialValues={queryInitialValues}
                onValuesChange={(changedValues, allValues) =>
                    onQueryChange &&
                    this.queryForm.current.setFieldsValue(onQueryChange(changedValues, allValues))
                }
            >
                {query}
                <Form.Item>
                    <Button.Group className="mr-xs">
                        <Button htmlType="submit" type="primary" icon={<AntIcon type="search" />}>
                            查询
                        </Button>
                        <Tooltip placement="bottom" title="重置查询">
                            <Button
                                onClick={() => this.onResetQuery(this.queryForm)}
                                icon={<AntIcon type="undo" />}
                            />
                        </Tooltip>
                    </Button.Group>
                    {moreQuery && (
                        <Button type="text" onClick={() => this.onOpenMoreQuery()}>
                            更多查询条件
                        </Button>
                    )}
                </Form.Item>
            </Form>
        </div>
    )
}

function renderMoreQueryBody() {
    const { moreQueryVisible } = this.state

    const { moreQuery, onQueryChange, queryInitialValues } = this.props

    return (
        <Drawer
            width={700}
            title="查询"
            className="yo-drawer-form"
            visible={moreQueryVisible}
            forceRender
            onClose={() => this.setState({ moreQueryVisible: false })}
        >
            <Form
                layout="vertical"
                ref={this.moreQueryForm}
                initialValues={queryInitialValues}
                onValuesChange={(changedValues, allValues) =>
                    onQueryChange &&
                    this.moreQueryForm.current.setFieldsValue(
                        onQueryChange(changedValues, allValues)
                    )
                }
            >
                <div className="yo-drawer-form--body">{moreQuery}</div>
                <div className="ant-drawer-footer">
                    <Button.Group>
                        <Button
                            htmlType="submit"
                            type="primary"
                            icon={<AntIcon type="search" />}
                            onClick={() =>
                                this.onQuery(this.moreQueryForm.current.getFieldsValue())
                            }
                        >
                            查询
                        </Button>
                        <Tooltip placement="top" title="重置查询">
                            <Button
                                onClick={() => this.onResetQuery(this.moreQueryForm)}
                                icon={<AntIcon type="undo" />}
                            />
                        </Tooltip>
                    </Button.Group>
                </div>
            </Form>
        </Drawer>
    )
}

function renderTable(props, on) {
    return <Table className="yo-table" {...props} {...on} />
}

export default class QueryTable extends Component {
    state = {
        // 加载状态
        loading: false,
        // 表格类型
        type: 'tree',
        // 数据
        dataSource: [],

        moreQueryVisible: false,
    }

    // 查询表单实例
    queryForm = React.createRef()
    // 更多查询表单实例
    moreQueryForm = React.createRef()

    // 查询值
    query = {}

    // 分页器配置
    pagination = {
        current: 1,
        pageSize: 10,
        total: 0,
        size: 'small',
        showSizeChanger: true,
        showQuickJumper: true,
        showTotal: total => `总共${total}条数据`,
        position: ['bottomLeft'],
    }

    // 默认选中页码
    pageIndex = 1
    // 默认页面尺寸
    pageSize = 10

    // 排序字段
    sorter = {
        sortField: '',
        sortOrder: '',
    }

    constructor(props) {
        super(props)

        this.autoLoad = typeof this.props.autoLoad === 'boolean' ? this.props.autoLoad : true
        this.loadData =
            typeof this.props.loadData === 'function' ? this.props.loadData : async () => {}

        this.rowNumber = typeof this.props.rowNumber === 'boolean' ? this.props.rowNumber : true

        if (this.props.pageIndex) {
            this.pageIndex = this.props.pageIndex
            this.pagination.current = this.pageIndex
        }
        if (this.props.pageSize) {
            this.pageSize = this.props.pageSize
            this.pagination.pageSize = this.pageSize
        }

        // 默认排序
        if (this.props.columns) {
            for (const column of this.props.columns) {
                if (column.defaultSortOrder) {
                    this.sorter = {
                        sortField: column.dataIndex,
                        sortOrder: column.defaultSortOrder,
                    }
                    break
                }
            }
        }
    }

    /**
     * 自动加载数据
     */
    componentDidMount() {
        if (this.autoLoad) {
            this.onLoadData()
        }
    }

    /**
     * 加载数据
     * 调用外部传入的loadData函数,可在loadData中自行改变参数
     */
    onLoadData = async () => {
        this.onLoading()

        if (isEqual(this.query, {}) && this.props.queryInitialValues) {
            this.query = this.props.queryInitialValues
        }

        try {
            const res = await this.loadData(
                {
                    pageIndex: this.pagination.current,
                    pageSize: this.pagination.pageSize,
                    ...this.sorter,
                },
                cloneDeep(this.query)
            )
            if (res.rows || res.data || res.items) {
                this.setState({
                    type: 'table',
                    dataSource: res.rows || res.data || res.items,
                })

                this.pagination.total = res.totalCount
            } else if (res) {
                this.setState({
                    type: 'tree',
                    dataSource: clearChildren(res),
                })

                this.pagination = false
            }
        } finally {
            this.onLoaded()
        }
    }

    /**
     * 数据开始加载
     */
    onLoading = () => {
        this.setState({
            loading: {
                indicator: <AntIcon type="loading" />,
            },
        })
    }

    /**
     * 数据加载完成
     */
    onLoaded = () => {
        this.setState({ loading: false })
    }

    /**
     * 进行查询
     * 返回表单字段值,加载数据,并且返回到第一页
     * @param {*} values
     */
    onQuery = values => {
        const { queryInitialValues } = this.props

        this.query = {
            ...queryInitialValues,
            ...this.query,
            ...values,
        }
        this.onReloadData(true)
    }

    /**
     * 重置查询
     * 初始化表单字段值,加载数据,并返回到第一页
     */
    onResetQuery = from => {
        const { queryInitialValues, onQueryChange, query, moreQuery } = this.props

        let queryValues = {}
        if (from === this.queryForm) {
            from.current.resetFields()
            queryValues = moreQuery ? this.moreQueryForm.current.getFieldsValue() : {}
        } else if (from === this.moreQueryForm) {
            from.current.resetFields()
            queryValues = query ? this.queryForm.current.getFieldsValue() : {}
        }

        this.query = {
            ...queryInitialValues,
            ...queryValues,
        }

        const changedValues = cloneDeep(this.query)
        onQueryChange && onQueryChange(changedValues, changedValues)
        this.onReloadData(true)
    }

    /**
     * 重新加载表格数据
     * @param {Boolean} resetPage 是否重置页码
     */
    onReloadData = (resetPage = false) => {
        if (resetPage) {
            this.pagination = {
                ...this.pagination,
                current: this.pageIndex,
            }
        }
        this.onLoadData()
    }

    /**
     * 表格分页/筛选/排序
     * @param {*} pagination
     * @param {*} filters
     * @param {*} sorter
     */
    onTableChange = (pagination, filters, sorter) => {
        this.pagination = {
            ...pagination,
            showTotal: total => `总共${total}条数据`,
        }
        this.sorter = {
            sortField: sorter.field,
            sortOrder: sorter.order,
        }
        this.onLoadData()
    }

    onAddRow = (record = {}) => {
        let { dataSource } = this.state
        if (!dataSource.find(item => !item.id)) {
            dataSource = [...dataSource, record]
            this.setState({
                dataSource,
            })
            return dataSource.length - 1
        }
        return false
    }

    onOpenMoreQuery = () => {
        this.setState({ moreQueryVisible: true })
    }

    getRecord = index => {
        const { dataSource } = this.state
        if (index === undefined) {
            return cloneDeep(dataSource)
        } else {
            return cloneDeep(dataSource[index])
        }
    }

    onChangeData = (index, changeData) => {
        let { dataSource } = this.state
        dataSource[index] = {
            ...dataSource[index],
            ...changeData,
        }
        dataSource = [...dataSource]
        this.setState({ dataSource })
    }

    render() {
        const { rowNumber } = this

        const { loading, dataSource, type } = this.state

        const {
            query,
            moreQuery,
            operator,
            columns,
            expandable,
            expandedRowRender,
            editable,
            formProps,
        } = this.props

        const attrs = {}
        Object.keys(this.props).forEach(key => {
            if (!propsMap.includes(key)) {
                attrs[key] = this.props[key]
            }
        })

        const props = {
            loading,
            pagination: this.pagination,
            dataSource,
            columns: (() => {
                const c = []
                if (type !== 'tree' && rowNumber & !expandable & !expandedRowRender) {
                    //c.push(rowNoColumn)
                }
                c.push(...(columns || []))
                return c.filter(p => !p.hidden)
            })(),
            bordered: true,
            size: 'middle',
            rowKey: record => record.id || Math.random().toString(16).slice(2),
            sticky: true,
            scroll: { x: 'max-content' },
            ...attrs,
        }

        const on = {
            onChange: (...args) => this.onTableChange.apply(this, args),
        }

        return (
            <section>
                {query && renderQueryBar.call(this)}
                <div className="yo-action-bar">
                    <div className="yo-action-bar--actions">{operator}</div>
                    <div className="yo-action-bar--actions">
                        <Button.Group>
                            <Tooltip placement="bottom" title="刷新">
                                <Button
                                    onClick={() => this.onReloadData()}
                                    type="text"
                                    icon={<AntIcon type="reload" />}
                                />
                            </Tooltip>
                        </Button.Group>
                    </div>
                </div>
                {editable ? (
                    <Form ref={this.props.form} {...formProps}>
                        {renderTable.call(this, props, on)}
                    </Form>
                ) : (
                    renderTable.call(this, props, on)
                )}
                {moreQuery && renderMoreQueryBody.call(this)}
            </section>
        )
    }
}
