import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { Table, Button, Pagination, Input, Checkbox, message } from 'antd'
import { get, uniq, uniqBy, cloneDeep, debounce, isEqual } from 'lodash'

class TableTransfer extends Component {
  constructor (props) {
    super(props)
    this.state = {
      // 穿梭框左边 Table 加载过的所有数据
      sourceDataAll: [],
      // 穿梭框左边 Table 数据源
      sourceTableData: [],
      // 穿梭框左边 Table 已选中项
      sourceSelectedKeys: [],
      // 穿梭框左边 Table 搜索项
      sourceSearchVal: '',
      // 穿梭框右边 Table 数据源
      targetTableData: [],
      // 穿梭框右边 Table 已选中项
      targetSelectedKeys: [],
      // 穿梭框右边 Table 搜索项
      targetSearchVal: '',
      // 穿梭框右边 Table 默认选中项
      defaultSelectedData: [],
      // Table 分页数据
      pagination: {
        current: 1,
        pageSize: 10
      },
      loading: false
    }
    this.debounceGetData = null
  }

  componentDidMount () {
    this.getData()
    this.debounceGetData = debounce(() => {
      this.state.pagination = { current: 1, pageSize: 10 }
      this.getData()
    }, 500)
  }

  getData = () => {
    this.setState({ loading: true })
    const { pagination, sourceSearchVal } = this.state
    this.props.getData({
      pagination,
      searchVal: sourceSearchVal
    }).then(res => {
      if (res) {
        const { rowKey, dataKeypath, selectedKeypath, totalKeypath } = this.props
        const sourceTableData = get(res, dataKeypath) || []
        const sourceDataAll = uniqBy([].concat(this.state.sourceDataAll, cloneDeep(sourceTableData)), rowKey)

        const selectedData = get(res, selectedKeypath) || []
        const paginationTotal = get(res, totalKeypath)
        let { targetTableData, defaultSelectedData, pagination } = this.state
        if (!isEqual(defaultSelectedData, selectedData)) {
          targetTableData = uniqBy([].concat(targetTableData, selectedData), rowKey)
          defaultSelectedData = cloneDeep(selectedData)
        }
        pagination.total = paginationTotal

        const defaultSelectedKeys = targetTableData.map(item => item[rowKey])
        sourceTableData.forEach(item => {
          item.disabled = defaultSelectedKeys.indexOf(item[rowKey]) !== -1
        })

        this.setState({ sourceDataAll, sourceTableData, targetTableData, defaultSelectedData, pagination })
      }
    }).finally(() => {
      this.setState({ loading: false })
    })
  }

  handleDataToRight = () => {
    const { rowKey, maxSelected } = this.props
    const { sourceDataAll, sourceTableData, sourceSelectedKeys, targetTableData } = this.state
    const selectedRows = sourceDataAll.filter(item => sourceSelectedKeys.indexOf(item[rowKey]) !== -1)
    if (!isNaN(maxSelected) && maxSelected > 0 && (targetTableData.length + selectedRows.length > maxSelected)) {
      message.warning(`最多可选${maxSelected}项`)
      return
    }
    sourceTableData.forEach(item => {
      if (sourceSelectedKeys.indexOf(item[rowKey]) !== -1) {
        item.disabled = true
      }
    })
    targetTableData.splice(0, 0, ...selectedRows)
    this.setState({ sourceSelectedKeys: [] }, this.handleDataChange)
  }

  handleDataToLeft = () => {
    const { rowKey } = this.props
    const { sourceTableData, targetTableData, targetSelectedKeys } = this.state
    sourceTableData.forEach(item => {
      if (targetSelectedKeys.indexOf(item[rowKey]) !== -1) {
        item.disabled = false
      }
    })
    this.state.targetTableData = targetTableData.filter(item => targetSelectedKeys.indexOf(item[rowKey]) === -1)
    this.setState({ targetSelectedKeys: [] }, this.handleDataChange)
  }

  handleDataChange = () => {
    const { targetTableData } = this.state
    this.props.onChange instanceof Function && this.props.onChange(targetTableData)
  }

  handlePaginationChange = (current, pageSize) => {
    this.setState({
      pagination: {
        ...this.state.pagination,
        current,
        pageSize
      }
    }, this.getData)
  }

  handleSelectedAll = (evt, type = 'source') => {
    if (type === 'source') {
      const selectedAllKeys = this.state.sourceTableData.filter(item => !item.disabled).map(item => item[this.props.rowKey])
      let { sourceSelectedKeys } = this.state
      if (evt.target.checked) {
        sourceSelectedKeys = uniq([].concat(sourceSelectedKeys, selectedAllKeys))
      } else {
        sourceSelectedKeys = sourceSelectedKeys.filter(item => selectedAllKeys.indexOf(item) === -1)
      }
      this.setState({ sourceSelectedKeys })
    } else {
      const showTargetData = this.checkShowTargetData()
      const selectedAllKeys = showTargetData.filter(item => !item.disabled).map(item => item[this.props.rowKey])
      let { targetSelectedKeys } = this.state
      if (evt.target.checked) {
        targetSelectedKeys = uniq([].concat(targetSelectedKeys, selectedAllKeys))
      } else {
        targetSelectedKeys = targetSelectedKeys.filter(item => selectedAllKeys.indexOf(item) === -1)
      }
      this.setState({ targetSelectedKeys })
    }
  }

  checkShowTargetData = () => {
    const { targetTableData, targetSearchVal } = this.state
    return targetTableData.filter(item => item[this.props.filterKey].indexOf(targetSearchVal) !== -1)
  }

  render () {
    const { rowKey, columns } = this.props
    const { sourceTableData, sourceSelectedKeys, targetTableData, targetSelectedKeys, pagination, loading } = this.state

    const showSourceDataKeys = sourceTableData.filter(item => !item.disabled).map(item => item[rowKey])
    const sourceCheckedAll = showSourceDataKeys.length && showSourceDataKeys.filter(key => sourceSelectedKeys.indexOf(key) === -1).length === 0
    const sourceIndeterminate = !sourceCheckedAll && sourceSelectedKeys.filter(key => showSourceDataKeys.indexOf(key) !== -1).length

    const showTargetData = this.checkShowTargetData()
    const showTargetDataKeys = showTargetData.filter(item => !item.disabled).map(item => item[rowKey])
    const targetCheckedAll = showTargetDataKeys.length && showTargetDataKeys.filter(key => targetSelectedKeys.indexOf(key) === -1).length === 0
    const targetIndeterminate = !targetCheckedAll && targetSelectedKeys.filter(key => showTargetDataKeys.indexOf(key) !== -1).length
    return (
      <div className='opt-table-transfer'>
        <div className='opt-table-transfer__source'>
          <div className='opt-table-transfer__search'>
            <Checkbox
              checked={sourceCheckedAll}
              indeterminate={sourceIndeterminate}
              onChange={this.handleSelectedAll}
            >
              <span>已选 <span style={{ color: '#5195f7' }}>{sourceSelectedKeys.length}</span> 项</span>
            </Checkbox>
            <Input.Search
              allowClear
              placeholder='请输入搜索内容'
              onChange={evt => { this.setState({ sourceSearchVal: evt.target.value }, this.debounceGetData) }}
            />
          </div>
          <div className='opt-table-transfer__table'>
            <Table
              size='middle'
              rowKey={rowKey}
              showHeader={false}
              pagination={false}
              loading={loading}
              columns={columns[0]}
              dataSource={sourceTableData}
              rowSelection={{
                columnWidth: 40,
                selectedRowKeys: sourceSelectedKeys,
                onChange: sourceSelectedKeys => { this.setState({ sourceSelectedKeys }) },
                getCheckboxProps: record => ({
                  disabled: targetTableData.map(item => item[rowKey]).indexOf(record[rowKey]) !== -1
                })
              }}
              onChange={this.handleTableChange}
            />
          </div>
          <Pagination showLessItems size='small' {...pagination} onChange={this.handlePaginationChange} />
        </div>
        <div className='opt-table-transfer__center'>
          <Button icon='right' onClick={this.handleDataToRight} />
          <Button icon='left' onClick={this.handleDataToLeft} />
        </div>
        <div className='opt-table-transfer__target'>
          <div className='opt-table-transfer__search'>
            <Checkbox
              checked={targetCheckedAll}
              indeterminate={targetIndeterminate}
              onChange={evt => this.handleSelectedAll(evt, 'target')}
            >
              <span>已选 <span style={{ color: '#5195f7' }}>{targetSelectedKeys.length}</span> 项</span>
            </Checkbox>
            <Input.Search
              allowClear
              placeholder='请输入搜索内容'
              onChange={evt => { this.setState({ targetSearchVal: evt.target.value }) }}
            />
          </div>
          <div className='opt-table-transfer__table'>
            <Table
              size='middle'
              rowKey={rowKey}
              showHeader={false}
              pagination={false}
              columns={columns[1] || columns[0]}
              dataSource={showTargetData}
              rowSelection={{
                columnWidth: 40,
                selectedRowKeys: targetSelectedKeys,
                onChange: targetSelectedKeys => { this.setState({ targetSelectedKeys }) }
              }}
            />
          </div>
          <Pagination showLessItems size='small' total={10} />
        </div>
      </div>
    )
  }
}

TableTransfer.propTypes = {
  rowKey: PropTypes.string,
  filterKey: PropTypes.string,
  maxSelected: PropTypes.number,
  getData: PropTypes.func.isRequired,
  columns: PropTypes.array.isRequired,
  onChange: PropTypes.func,
  dataKeypath: PropTypes.string,
  selectedKeypath: PropTypes.string,
  totalKeypath: PropTypes.string
}

TableTransfer.defaultProps = {
  rowKey: 'key',
  filterKey: 'title',
  dataKeypath: 'Data.dataSource',
  selectedKeypath: 'Data.selectedData',
  totalKeypath: 'TotalCount'
}

export default TableTransfer
