/**
 * 图表列表
 */
import React from 'react'
import { Layout, Button, Icon, Input, Menu, Dropdown, Card, Col, Row, Popover, Breadcrumb, Tree, Tag } from 'antd'
import { connect } from 'dva'
import './list.less'
import ChooseDataSourceBox from './chooseDataSourceBox'
import { dateFormat } from '../../utils/baseUtils'
import Ellipsis from 'ant-design-pro/lib/Ellipsis'
import 'ant-design-pro/dist/ant-design-pro.css'
import GroupSelector from '../datasource/groupSelector'
import Thumbnail from './thumbnail'
import DistributeBox from './distributeBox';
import TransferBox from '../common/selectUserBox/selectUserBox'
import DeleteBox from '../common/deleteBox/deleteBox'
const { Content } = Layout
const { Search } = Input
const CardGrid = Card.Grid
const { TreeNode } = Tree


class ChartList extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            selectedRecord: null,
            visibleChooseDataSourceBox: false,
            visibleDistributeBox: false,
            visibleTransferBox: false,
            visibleGroupMenu: false, // 显示分组菜单
            visibleDeleteBox: false
        }
    }

    componentDidMount() {
        const { dispatch } = this.props;
        this.setBodyWidth();
        dispatch({ type: 'chart/fetchList' });
        dispatch({ type: 'chart/remoteGroupList' });
    }

    /**
     * 设置卡片容器宽度 = 每行最大卡片数量 * 卡片宽度
     */
    setBodyWidth() {
        const chartBody = document.getElementsByClassName('chart-body')[0]; // 卡片容器
        const parent = chartBody.parentNode; // 父级容器
        const pWidth = parent.offsetWidth; // 父级容器宽度
        const pPadding = 10 + 10; // 父级容器左右padding
        const cWidth = 207; // 每个卡片宽度
        const cMargin = 5 + 5; // 每个卡片左右margin
        const pTrueWidth = pWidth - pPadding; // 父容器实际可用宽度
        const cTrueWidth = cWidth + cMargin; // 卡片实际占用宽度
        const count = Math.floor(pTrueWidth/cTrueWidth); // 每行最大卡片数量

        chartBody.style.width = count * cTrueWidth  + 'px';
    }

    generateCard() {
        const { chart, dispatch } = this.props;
        const groupList = chart.groupList;
        const { selectedRecord } = this.state;
        const list = chart.list;
        const currentGroup = chart.currentGroup;

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

        const operationMenu = (
            <Menu className='menu-operation'>
                <Menu.Item onClick={() => {
                    const { selectedRecord } = this.state;
                    // const selectedChartDataSourceCode = selectedRecord ? selectedRecord.code : '';
                    const selectedChartCode = selectedRecord ? selectedRecord.code : '';
                    dispatch({ type: 'chartPolicy/fetchList', chartCode: selectedChartCode });
                    dispatch({ type: 'chartPolicy/remoteColumnData', chartCode: selectedChartCode });
                    // dispatch({ type: 'chartDesigner/remoteDataColumn', code:  });
                    this.setState({visibleDistributeBox: true})
                }}> 
                    <Icon type='share-alt'/>分发
                </Menu.Item>
                <Menu.SubMenu className='setgroupmenu' title={<div><Icon style={{ marginRight: '6px' }} type='profile' />移动到</div>}>
                    {this.createGroupMenu(selectedRecord)}
                </Menu.SubMenu>
                <Menu.Divider />
                <Menu.Item
                    onClick={()=>{
                        this.setState({ visibleTransferBox: true})
                    }}
                >
                    <Icon type="swap" />移交
                </Menu.Item>
                <Menu.Item
                    onClick={(e) => {
                        this.setState({ visibleDeleteBox: true})
                    }}
                >
                    <Icon type="delete" />删除
                    
                </Menu.Item>
            </Menu>
        )
        
        let groupFilter = groupList.concat({ code: '-1', label: '未分组' }).filter(g => (
            currentGroup[0].code === 'all' || 
            (
                currentGroup[0].code === '-1' ? g.code === '-1' : (
                    currentGroup[1] ? (g.code === currentGroup[1].code) : 
                    (
                        g.code === currentGroup[0].code ||
                        g.pcode === currentGroup[0].code
                    )
                )
            )
        )).map(g => g.code);


        let cards = list.filter(l => groupFilter.indexOf(l.groupCode+'') !== -1).map(l => {
            let reg = new RegExp('(' + filterLabel + '){1}', 'ig');
            if((l.name || '').search(reg) !== -1 || (l.description || '').search(reg) !== -1) {
                return { ...l, bf: false };
            }else {
                return { ...l, bf: true };
            }
        }).sort((a, b) => {
            return new Date(b.createTime) - new Date(a.createTime)
        }).map( (l, i) => (
            <CardGrid className={`chart-card${l.bf?' chart-card-hide':''}`} key={i} onClick={() => {
                this.setState({ selectedRecord: l })
            }}>
                <Card
                    title={
                        <Row type='flex' justify='space-between'>
                            <Col span={21} style={{ overflow: 'hidden', textOverflow: 'ellipsis' }} >
                                { filterLabel ?
                                    ((l.name || '').split(new RegExp(`(${filterLabel})`, 'i')).map((fragment, i) => {
                                        return (
                                            fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') === filterLabel.toLowerCase() ?
                                            <span key={i} style={{fontWeight: 'bold', color: 'red'}} className="highlight">{fragment}</span> :
                                            fragment
                                        )
                                    }
                                    )) : l.name
                                }
                            </Col>
                            <Col style={{ textAlign: 'right' }} span={3} >
                                <Icon type='star-o'/>
                            </Col>
                        </Row>
                    }
                    cover={
                        <Col className='cover-body'>
                            <Row className='thumb' onClick={() => {
                                dispatch({ type: 'chartDesigner/reset' });
                                dispatch({ type: 'main/redirect', path: '/chart/' + l.code });
                            }}>
                                {/* <div className='deny-body'>
                                    <div className='deny-tip'>您没有对应数据源的权限</div>
                                </div> */}
                                <Thumbnail type={l.type} code={l.code} option={l.chartOption}/>
                            </Row>
                            <Row className='desc'>
                                <Ellipsis tooltip={l.description&&l.description.length > 16} lines={2}>{
                                    <span>
                                    { filterLabel ?
                                        ((l.description || '').split(new RegExp(`(${filterLabel})`, 'i')).map((fragment, i) => {
                                            return (
                                                fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') === filterLabel.toLowerCase() ?
                                                <span key={i} style={{fontWeight: 'bold', color: 'red'}} className="highlight">{fragment}</span> :
                                                fragment
                                            )
                                        }
                                        )) : l.description
                                    }
                                    </span>
                                }</Ellipsis>
                            </Row>
                            <Row className='footer' type='flex' justify='end' align='bottom'>
                                <Col style={{ textAlign: 'left' }} span={22}>
                                    <Row>{l.creator} {dateFormat(l.createTime, 'yyyy-MM-dd')}</Row>
                                </Col>
                                <Col span={2} style={{ textAlign: 'right' }}>
                                    <Dropdown overlay={operationMenu} trigger={['click']}>
                                        <Icon type="ellipsis" />
                                    </Dropdown>
                                </Col>
                            </Row>
                        </Col>
                    }
                >
                </Card>
            </CardGrid>
        ));
        if(cards.length === 0) {
            cards = <div style={{ padding: '7px', textAlign: 'center', fontSize: '14px', color: 'rgba(0, 0, 0, 0.45)' }}>暂无数据</div>
        }
        return cards;
    }

    createGroupMenu = (selectedRecord) => {
        const { chart, dispatch } = this.props;
        const groupList = chart.groupList;
        const pGroups = groupList.filter(d => d.pcode === '-1').sort((a, b) => a.index - b.index);
        const cGroups = groupList.filter(d => d.pcode !== '-1');

        let allGroups = !!selectedRecord ? [
            { code: '-1', label: '未分组' }
        ].concat(pGroups) : [
            { code: 'all', label: '全部分组' },
            { code: '-1', label: '未分组' }
        ].concat(pGroups);

        return allGroups.map(p => {
            let c = cGroups.filter(c => c.pcode === p.code).sort((a, b) => a.index - b.index);
            return c.length > 0 ? (
                <Menu.SubMenu key={p.code} title={<span style={{ fontWeight: !!selectedRecord ? 
                    (p.code+'' === selectedRecord.groupCode+'' ? 'bold' : (
                        c.find(ch => ch.code+'' === selectedRecord.groupCode+'') && c.find(ch => ch.code+'' === selectedRecord.groupCode+'').pcode === p.code ? 'bold' : 'normal'
                    ))
                : chart.currentGroup[0].code === p.code ? 'bold' : 'normal' }}>{p.label}</span>} onTitleClick={(item) => {
                    dispatch({ type: 'chart/setCurrentGroup', group1: p });
                    if(selectedRecord) {
                        dispatch({ type: 'chart/remoteSetChartGroup', chart: selectedRecord, group: p });
                    }
                    this.hideGroupMenu();
                }}>
                    {c.map(c => {
                        return (<Menu.Item key={c.code} onClick={(item) => {
                            dispatch({ type: 'chart/setCurrentGroup', group1: p, group2: c });
                            if(selectedRecord) {
                                dispatch({ type: 'chart/remoteSetChartGroup', chart: selectedRecord, group: c });
                            }
                        }}><span style={{ fontWeight: !!selectedRecord ? (
                            selectedRecord.groupCode+'' === c.code+'' ? 'bold' : 'normal'
                        ) : (chart.currentGroup[1] && (chart.currentGroup[1].code === c.code) ? 'bold' : 'normal') }}>{c.label}</span></Menu.Item>)
                    })}
                </Menu.SubMenu>
            ) : (
                <Menu.Item key={p.code} onClick={() => {
                    dispatch({ type: 'chart/setCurrentGroup', group1: p });
                    if(selectedRecord) {
                        dispatch({ type: 'chart/remoteSetChartGroup', chart: selectedRecord, group: p });
                    }
                    this.hideGroupMenu();
                }}><span style={{ fontWeight: !!selectedRecord ? (
                    selectedRecord.groupCode+'' === p.code+'' ? 'bold' : 'normal'
                ) : chart.currentGroup[0] && (chart.currentGroup[0].code === p.code) ? 'bold' : 'normal' }}>{p.label}</span></Menu.Item>
            );
        });
    }

    createSubGroupMenu = () => {
        const { chart, dispatch } = this.props;
        const groupList = chart.groupList;
        const parentGroup = chart.currentGroup[0];
        const children = groupList.filter(d => d.pcode === parentGroup.code);
        const subGroup = chart.currentGroup[1];

        return children.map(c => {
            return (
                <Menu.Item key={c.code} onClick={() => {
                    dispatch({ type: 'chart/setCurrentGroup', group1: parentGroup, group2: c });
                }}><span style={{ fontWeight: subGroup && (subGroup.code === c.code) ? 'bold' : 'normal' }}>{c.label}</span></Menu.Item>
            );
        })
    }

    createGroupTree(modify) {
        const { dispatch, chart } = this.props;
        const { groupEditing } = this.state;
        const groupList = chart.groupList;

        let parent = groupList.filter(d => d.pcode === '-1').sort((a, b) => a.index - b.index);
        let children = groupList.filter(d => d.pcode !== '-1');

        let groupTree = parent.map(p => {
            return (
                <TreeNode disabled={groupEditing} title={
                modify ? (<div><Icon style={{ cursor: 'move' }} type='drag'/>
                <Input value={p.label} size='small' focus={'true'} onFocus={() => {
                    this.setState({
                        groupEditing: true
                    });
                }} onChange={(e) => {
                    dispatch({ type: 'chart/modifyGroup', group: {...p, label:e.target.value} });
                }} onBlur={(e) => {
                    this.setState({
                        groupEditing: false
                    });
                    dispatch({ type: 'chart/remoteModifyGroup', group: {...p, label:e.target.value} });
                }} onPressEnter={(e) => {
                    dispatch({ type: 'chart/remoteModifyGroup', group: {...p, label:e.target.value} });
                }} /><Icon type='plus-circle-o' onClick={() => {
                    dispatch({ type: 'chart/remoteAddGroup', pgroup: p });
                }}/><Icon type='minus-circle' onClick={() => {
                    dispatch({ type: 'chart/remoteDeleteGroup', group: p });
                }}/></div>) : p.label} key={p.code}>
                    {
                        children.filter(c => c.pcode === p.code).sort((a, b) => a.index - b.index).map(c => {
                            return (
                                <TreeNode disabled={groupEditing} title={
                                    modify ? (<div><Icon style={{ cursor: 'move' }} type='drag'/>
                                    <Input value={c.label} size='small' onFocus={() => {
                                        this.setState({
                                            groupEditing: true
                                        });
                                    }} onChange={(e) => {
                                        dispatch({ type: 'chart/modifyGroup', group: {...c, label:e.target.value} });
                                    }} onBlur={(e) => {
                                        this.setState({
                                            groupEditing: false
                                        });
                                        dispatch({ type: 'chart/remoteModifyGroup', group: {...c, label:e.target.value} });
                                    }} onPressEnter={(e) => {
                                        dispatch({ type: 'chart/remoteModifyGroup', group: {...c, label:e.target.value} });
                                    }} onCompositionEnd={(e) => {
                                        console.log(e.target.value);
                                    }}/><Icon type='minus-circle' onClick={() => {
                                        dispatch({ type: 'chart/remoteDeleteGroup', group: c });
                                    }}/></div>) : p.label
                                } key={c.code} />
                            )
                        })
                    }
                </TreeNode>
            )
        });

        return groupTree;
    }

    handleVisibleChange = (flag) => {
        this.setState({ visibleGroupMenu: flag });
    }

    hideGroupMenu = () => {
        this.setState({
            visibleGrouMenu: false
        });
    }

    onDrop = (info) => {
        const { dispatch } = this.props;

        const dropCode = info.node.props.eventKey;
        const dragCode = info.dragNode.props.eventKey;
        const dropPos = info.node.props.pos.split('-');
        const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1]); // -1/0/1 -> 兄/子/弟
        console.log(dragCode, dropCode, dropPosition);
        dispatch({ type: 'chart/remoteMoveGroup', dragCode, dropCode, dropPosition });
    }

    render() {
        const { visibleChooseDataSourceBox, visibleDistributeBox, visibleTransferBox, visibleDeleteBox, selectedRecord } = this.state;
        const { dispatch, chart } = this.props;
        const TAG_COLOR = ['blue'];
        return (
            <Layout className='chart-list'>
                <Content>
                    <Card title={
                        <Row className='tools' type='flex' justify='space-between'>
                            <Col style={{ display: 'flex' }}>
                            <Popover overlayClassName='popover-group' title={
                                    <Row className='grouptree-title' type='flex' justify='space-between'>
                                        <Col>
                                            分组管理
                                        </Col>
                                        <Col>
                                            <div className='create-group' onClick={() => {
                                                dispatch({ type: 'chart/remoteAddGroup' });
                                            }}>添加分组<Icon type="plus-circle-o" /></div>
                                        </Col>
                                    </Row>
                                } trigger="click" placement="bottomLeft" content={(
                                    <Tree
                                        className='tree-group'
                                        showLine
                                        defaultExpandAll
                                        draggable
                                        onDragStart={this.onDragStart}
                                        onDrop={this.onDrop}
                                    >
                                        {
                                            this.createGroupTree(true)
                                        }
                                    </Tree>
                                )}>
                                    <Icon type="bars" />
                                </Popover>
                                <Breadcrumb className='group' separator=">">
                                    <Breadcrumb.Item>
                                        <GroupSelector model={chart} modelName='chart'>
                                            <Tag color={TAG_COLOR[Math.ceil(Math.random()*TAG_COLOR.length) - 1]} >
                                                {chart.currentGroup[0].label}
                                            </Tag>
                                        </GroupSelector>
                                    </Breadcrumb.Item>
                                    {chart.currentGroup[1] && (<Breadcrumb.Item>
                                        <GroupSelector model={chart} modelName='chart'>
                                            <Tag color={TAG_COLOR[Math.ceil(Math.random()*TAG_COLOR.length) - 1]}>
                                                {chart.currentGroup[1].label}
                                            </Tag>
                                        </GroupSelector>
                                    </Breadcrumb.Item>)}
                                </Breadcrumb>
                            </Col>
                            <Col className='search'>
                                <Col style={{ padding: '0 5px' }}>
                                    <Search
                                        placeholder="请输入关键字"
                                        value={chart.filterLabel}
                                        onChange={e => {
                                            dispatch({ type: 'chart/setFilterLabel', label: e.target.value });
                                        }}
                                    />
                                </Col>
                                <Col >
                                    <Button onClick={() => {
                                        dispatch({ type: 'dataSource/fetchList' });
                                        this.setState({
                                            visibleChooseDataSourceBox: true
                                        });
                                    }}>
                                        <Icon type="area-chart" />创建图表
                                    </Button>
                                    <ChooseDataSourceBox visibleChooseDataSourceBox={visibleChooseDataSourceBox} hideBox={() => {
                                        this.setState({
                                            visibleChooseDataSourceBox: false
                                        });
                                    }}/>
                                </Col>
                            </Col>
                        </Row>
                    }>
                        <div className='chart-body'>
                            { this.generateCard() }
                        </div>
                    </Card>
                </Content>
                <DistributeBox key={this.state.selectedRecord ? this.state.selectedRecord.code : 'notkey'} visibleDistributeBox={visibleDistributeBox} selectedRecord={this.state.selectedRecord} hideBox={() => {
                    this.setState({
                        visibleDistributeBox: false
                    });
                }} />
                <TransferBox
                    visibleBox={visibleTransferBox}
                    title='选择移交对象'
                    okHandler={(user) => {
                        dispatch({ type: 'chart/transfer', chartCode: this.state.selectedRecord.code, userCode: user.code });
                    }}
                    hideBox={() => {
                        this.setState({
                            visibleTransferBox: false
                        })
                    }}
                />
                <DeleteBox
                    visibleDeleteBox={visibleDeleteBox}
                    type='chart'
                    hideBox={() => {
                        this.setState({
                            visibleDeleteBox: false
                        })
                    }}
                    selectedRecord={selectedRecord}
                    onOk={() => {
                        dispatch({ type: 'chart/remoteDelete', code: this.state.selectedRecord.code })
                    }} />
            </Layout>
        )
    }
}


function mapStateToProps(state) {
    return { chart: state.present.chart }
}

export default connect(mapStateToProps)(ChartList)