import React from 'react'
import { Modal, Tabs, Table, Checkbox, Row, Col, Input } from 'antd'
import { connect } from 'dva'
import './accessObjectBox.less'
const { TabPane } = Tabs
const { Search } = Input


class AccessObjectBox extends React.Component {
    
    constructor(props) {
        super(props);
        this.state = {
            groupFilterLabel: '',
            userFilterLabel: '',
            selectedGroups: props.defaultSelectedGroups && props.defaultSelectedGroups.length >= 0 ? props.defaultSelectedGroups : [],
            selectedUsers: props.defaultSelectedUsers && props.defaultSelectedUsers.length >= 0 ? props.defaultSelectedUsers : [],
            columnWidth: 100,
            boxHeight: 0,
            tableHeaderHeight: 60,
            groupLimit: 30,
            userLimit: 30,
        }
    }

    componentDidMount() {
        const { dispatch } = this.props;
        new Promise(() => {
            dispatch({ type: 'userGroup/fetchList' });
            dispatch({ type: 'user/fetchList' })
        })
    }
    
    getAccessObject = () => {
        const { okHandler, hideBox } = this.props;
        const { selectedGroups, selectedUsers } = this.state;
        typeof okHandler === 'function' && okHandler(selectedGroups, selectedUsers);
        typeof hideBox === 'function' && hideBox();
    }

    render() {
        const { visibleBox, hideBox, userGroup, user, defaultSelectedGroups: _defaultSelectedGroups, defaultSelectedUsers: _defaultSelectedUsers } = this.props;
        const { selectedGroups, selectedUsers, columnWidth, groupLimit, userLimit } = this.state;

        const defaultSelectedGroups = _defaultSelectedGroups && _defaultSelectedGroups.length >= 0 ? _defaultSelectedGroups : [];
        const defaultSelectedUsers = _defaultSelectedUsers && _defaultSelectedUsers.length >= 0 ? _defaultSelectedUsers : [];

        const reg = new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'); // 需要转义的字符
        let groupFilterLabel = (this.state.groupFilterLabel || '').replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1'); // 添加转义符号
        let userFilterLabel = (this.state.userFilterLabel || '').replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1'); // 添加转义符号

        const userGroupColumns = [{
            key: 'check',
            title: '选择',
            render: (v, r, i) => <Checkbox
                dataKey={r.key}
                checked={!!defaultSelectedGroups.find(g => g.code === r.code) || !!selectedGroups.find(g => g.code === r.code)}
                onChange={(e) => {
                    const target = e.target;
                    const checked = target.checked;
                    let { selectedGroups } = this.state;
                    if(checked) {
                        selectedGroups.push({
                            code: r.code,
                            name: r.name,
                            isGroup: true
                        });
                    }else {
                        let index = selectedGroups.findIndex(g => g.code === r.code);
                        selectedGroups.splice(index, 1);
                    }
                    this.setState({ selectedGroups });
                }}
            />,
            width: 50
        }, {
            key: 'name',
            title: '名称',
            dataIndex: 'name',
            width: 400,
            render: value => <span>
                { groupFilterLabel ?
                    ((value || '').split(new RegExp(`(${groupFilterLabel})`, 'i')).map((fragment, i) => {
                        return (
                            fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') === groupFilterLabel.toLowerCase() ?
                            <span key={i} style={{fontWeight: 'bold', color: 'red'}} className="highlight">{fragment}</span> :
                            fragment
                        )
                    }
                    )) : value
                }
            </span>,
        }];
        const userColumns = [{
            key: 'check',
            title: '选择',
            render: (v, r, i) => <Checkbox
                dataKey={r.key}
                checked={!!defaultSelectedUsers.find(g => g.code === r.code) || !!selectedUsers.find(g => g.code === r.code)}
            />,
            width: 50
        }, {
            key: 'fullName',
            title: '名称',
            dataIndex: 'fullName',
            width: 400,
            render: value => <span>
                { userFilterLabel ?
                    ((value || '').split(new RegExp(`(${userFilterLabel})`, 'i')).map((fragment, i) => {
                        return (
                            fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') === userFilterLabel.toLowerCase() ?
                            <span key={i} style={{fontWeight: 'bold', color: 'red'}} className="highlight">{fragment}</span> :
                            fragment
                        )
                    }
                    )) : value
                }
            </span>,
        }]

        return (
            <Modal
                className='accessobject-box'
                width='60%'
                height='80%'
                title='选择用户组或用户'
                visible={visibleBox}
                onCancel={hideBox}
                onOk={this.getAccessObject}
                maskClosable={false}
                destroyOnClose={true}
            >
                <Tabs
                    type='card'
                    className='accessobject-tabs'
                    defaultActiveKey="userGroup"
                >
                    <TabPane tab="用户组" key="userGroup" >
                        <TableList
                            refName='grouptable'
                            filterLabel={this.state.groupFilterLabel}
                            onFilterLabelChange={(val) => {
                                this.setState({
                                    groupFilterLabel: val
                                });
                            }}
                            columns={userGroupColumns.map(c => ({
                                ...c, width: columnWidth
                            }))}
                            dataSource={userGroup.list.filter(l => {
                                let reg = new RegExp('(' + groupFilterLabel + '){1}', 'ig');
                                return (l.name || '').search(reg) !== -1;
                            }).slice(0, groupLimit).map((l, i) => ({
                                ...l,
                                key: i
                            }))}
                            onRowClick={(record) => {
                                const idx = selectedGroups.findIndex(i => i.code === record.code);
                                if(idx === -1) {
                                    selectedGroups.push({
                                        code: record.code,
                                        name: record.name,
                                        isGroup: true
                                    });
                                }else {
                                    selectedGroups.splice(idx, 1);
                                }
                                this.setState({
                                    selectedGroups: selectedGroups
                                })
                            }}
                        />
                    </TabPane>
                    <TabPane tab="用户" key="user" >
                        <TableList
                            refName='usertable'
                            filterLabel={this.state.userFilterLabel}
                            onFilterLabelChange={(val) => {
                                this.setState({
                                    userFilterLabel: val
                                });
                            }}
                            columns={userColumns.map(c => ({
                                ...c,
                                width: columnWidth
                            }))}
                            dataSource={user.list.filter(l => {
                                let reg = new RegExp('(' + userFilterLabel + '){1}', 'ig');
                                return (l.fullName || '').search(reg) !== -1;
                            }).slice(0, userLimit).map((l, i) => ({
                                ...l,
                                key: i
                            }))}
                            onRowClick={(record) => {
                                const idx = selectedUsers.findIndex(i => i.code === record.code);
                                if(idx === -1) {
                                    selectedUsers.push({
                                        code: record.code,
                                        name: record.fullName,
                                        isGroup: false
                                    });
                                }else {
                                    selectedUsers.splice(idx, 1);
                                }
                                this.setState({
                                    selectedUsers: selectedUsers
                                })
                            }}
                        />
                    </TabPane>
                </Tabs>
            </Modal>
        )
    }
}

class TableList extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            pageSize: 0,
            tableScrollHeight: 0,
            currentPage: 1,
        };
    }

    componentDidMount() {
        this.resetTableScrollSize();
        window.addEventListener('resize', this.resetTableScrollSize);
    }

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

    resetTableScrollSize = () => {
        const { refName } = this.props;
        const tableWrapper = this[refName].getElementsByClassName('object-table')[0];
        const content = tableWrapper.getElementsByClassName('ant-spin-nested-loading')[0];
        const tableHeader = content.querySelector('thead');
        // 容器高度 - 分页器高度 - 表头高度
        let tableScrollHeight = tableWrapper.offsetHeight - 42 - tableHeader.offsetHeight - 10;
        this.setState({
            tableScrollHeight,
            pageSize: Math.ceil((tableScrollHeight) / 38)
        });
    }

    onPageChange = page => {
        this.setState({
            currentPage: page
        });
    }
    
    render() {
        const { refName, filterLabel, onFilterLabelChange, columns, dataSource, onRowClick } = this.props;
        const { tableScrollHeight, pageSize, currentPage } = this.state;

        return <div ref={node => this[refName] = node} className='table-list'>
            <Row type='flex' justify='end' style={{ position: 'absolute', right: 0, top: 0 }}>
                <Col style={{ padding: '8px' }}><Search 
                    placeholder="请输入关键字"
                    value={filterLabel}
                    onChange={e => {
                        this.setState({
                            currentPage: 1,
                        });
                        onFilterLabelChange && onFilterLabelChange(e.target.value + '');
                    }}
                /></Col>
            </Row>
            <Table
                className='object-table'
                columns={columns}
                dataSource={dataSource}
                size='small'
                pagination={{
                    pageSize: pageSize,
                    current: currentPage,
                    onChange: this.onPageChange
                }}
                scroll={{
                    x: false,
                    y: tableScrollHeight
                }}
                onRow={(record) => {
                    return {
                        onClick: () => {
                            onRowClick && onRowClick(record)
                        }
                    };
                }}
            />
        </div>
    }
}

export default connect(({ present: { userGroup, user } }) => ({ userGroup, user }))(AccessObjectBox);