import React, { Component } from 'react'
import { Button, Form, List, Pagination, Spin, Tooltip } from 'antd'
import { AntIcon } from 'components'
import { cloneDeep } from 'lodash'

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

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

    return (
        <div className="yo-query-bar">
            <Form
                layout="inline"
                ref={this.form}
                onFinish={value => this.onQuery(value)}
                initialValues={this.props.queryInitialValues}
            >
                {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()}
                                icon={<AntIcon type="undo" />}
                            />
                        </Tooltip>
                    </Button.Group>
                    {moreQuery && <Button>更多查询条件</Button>}
                </Form.Item>
            </Form>
        </div>
    )
}

export default class QueryList extends Component {
    state = {
        loading: false,
        dataSource: [],

        ping: [],
    }

    // 查询表单实例
    form = React.createRef()

    // 查询值
    query = {}

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

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

    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 () => {}

        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
        }
    }

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

        window.addEventListener('resize', this.onResizeScroll)
    }

    componentWillUnmount() {
        window.removeEventListener('resize', this.onResizeScroll)
    }

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

        const res = await this.loadData(
            {
                pageIndex: this.pagination.current,
                pageSize: this.pagination.pageSize,
            },
            cloneDeep(this.query)
        )

        this.setState(
            {
                dataSource: res.rows || res.data || res.items,
            },
            () => {
                this.onResizeScroll()
            }
        )

        this.pagination.total = res.totalCount

        this.onLoaded()
    }

    /**
     * 数据开始加载
     */
    onLoading = () => {
        this.setState({ loading: true })
    }

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

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

    /**
     * 重置查询
     * 初始化表单字段值,加载数据,并返回到第一页
     */
    onResetQuery = () => {
        this.form.current.resetFields()
        this.query = {}
        this.onReloadData(true)
    }

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

    onListChange = (current, pageSize) => {
        this.pagination = {
            ...this.pagination,
            current,
            pageSize,
        }
        this.onLoadData()
    }

    onResizeScroll = () => {
        this.onListScrollX({ target: this.refs['scroll-x'] })
    }

    onListScrollX(e) {
        const { offsetWidth, scrollWidth, scrollLeft } = e.target
        const ping = []
        if (offsetWidth + scrollLeft < scrollWidth && scrollLeft > 0) {
            ping.push(...['left', 'right'])
        } else if (offsetWidth + scrollLeft < scrollWidth) {
            ping.push('right')
        } else if (offsetWidth + scrollLeft >= scrollWidth && offsetWidth < scrollWidth) {
            ping.push('left')
        }
        this.setState({ ping })
    }

    render() {
        const { loading, dataSource, ping } = this.state

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

        const props = {
            dataSource: this.state.dataSource,
            rowKey: record => record.id || Math.random().toString(16).slice(2),
            ...attrs,
        }

        return (
            <section>
                {this.props.query && renderQueryBar.call(this)}
                <div className="yo-action-bar">
                    <div className="yo-action-bar--actions">{this.props.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>
                <div className="yo-list">
                    <Spin spinning={loading} indicator={<AntIcon type="loading" />}>
                        <div
                            className={['yo-list-container', ...ping.map(p => `yo-list--ping-${p}`)]
                                .filter(p => p)
                                .join(' ')}
                        >
                            <div
                                className="yo-list--scroll"
                                ref="scroll-x"
                                onScroll={e => this.onListScrollX(e)}
                            >
                                <List {...props} />
                            </div>
                        </div>
                        {!!dataSource && !!dataSource.length && (
                            <Pagination
                                size="small"
                                {...this.pagination}
                                onChange={(current, pageSize) =>
                                    this.onListChange(current, pageSize)
                                }
                            />
                        )}
                    </Spin>
                </div>
            </section>
        )
    }
}
