import React from 'react'
import { Form, Input, InputNumber, DatePicker, Select, Spin, Divider, Icon, Tag } from 'antd'
import * as service from '../../../services/index'
import URLS from '../../../constants/url'
import moment from 'moment'
import './filter.less'
const { Option: SelectOption } = Select
const FormItem = Form.Item

class Filter extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            fetching: false,
            columnData: [],
            dropdownOpen: false,
        }
    }

    generatFilter = () => {
        const { filter } = this.props;
        const { label, operator, operatorLabel } = filter;
        
        return <div className='filter'>
            <span className='filter-name'>{label + ' ' + operatorLabel + ' : '}</span>
            <FormItem className='filter-value filter-value1'>
                { this.generateValueItem(filter, 1) }
            </FormItem>
            { operator === 'between' && <FormItem className='filter-value filter-value2'>
                { this.generateValueItem(filter, 2) }
            </FormItem> }
        </div>
    }

    generateTimeTags = (filter, index, defaultValue) => {
        const timeTypes = [
            { dynamic: true, label: '今天', name: 'today' },
            { dynamic: true, label: '本月', name: 'month' },
            { dynamic: true, label: '上月', name: 'lastmonth' },
            { dynamic: true, label: '近半年', name: 'halfyear' },
            { dynamic: true, label: '本年', name: 'year' },
            { dynamic: true, label: '上年', name: 'lastyear' },
        ]
        return timeTypes.map(t => <Tag key={t.name} className={`cus-time-tag${defaultValue && defaultValue.name === t.name ? ' current' : ''}`} onClick={() => {
            this.changeFilterValue(filter, t, index);
            let obj = {};
            obj['datePickerOpen' + index] = false;
            this.setState(obj);
        }}>{t.label}</Tag>);
    }

    generateValueItem = (filter, index) => {
        const { fetching, columnData, dropdownOpen } = this.state;
        let field;
        let { key, type, operator } = filter;

        let defaultValue = type==='time' ? ( filter['value' + index] ? ( filter['value' + index].dynamic ? ( filter['value' + index] ) : moment(filter['value' + index]) ) : null ) : filter['value' + index]
        const commonProps = { defaultValue }

        if(['index', 'string'].indexOf(type) !== -1) {
            field = <Input key={Math.random()} { ...commonProps } onBlur={(e) => {
                if(e.target.value !== commonProps.defaultValue) {
                    this.changeFilterValue(filter, e.target.value, index)
                }
            }} onPressEnter={e => {
                if(e.target.value !== commonProps.defaultValue) {
                    this.changeFilterValue(filter, e.target.value, index)
                }
            }}/>
        }else if(['scale', 'ordinal'].indexOf(type) !== -1) {
            field = <InputNumber key={Math.random()} { ...commonProps } onBlur={(e) => {
                if(e.target.value !== commonProps.defaultValue) {
                    this.changeFilterValue(filter, e.target.value, index)
                }
            }} onKeyDown={e => {
                if(e.keyCode === 13 && e.target.value !== commonProps.defaultValue) {
                    this.changeFilterValue(filter, e.target.value, index)
                }
            }}/>
        }else if(type === 'time') {
            field = <div className='cus-time-picker' >
                <Input
                    key={Math.random()}
                    allowClear
                    // suffix={<Icon style={{ color: 'rgba(0, 0, 0, 0.25)' }} type="calendar" />}
                    defaultValue={ commonProps.defaultValue ? (commonProps.defaultValue.dynamic ? commonProps.defaultValue.label : moment(commonProps.defaultValue).format('YYYY-MM-DD')) : '' }
                    onFocus={(e) => {
                        let obj = {};
                        obj['datePickerOpen' + index] = true;
                        this.setState(obj);
                    }}
                    onChange={() => {
                        // 因为onFocus方法弹出了浮层，onChange方法只在点击清楚图标时会调用（相当于不可编辑的input），所以这里只做清除
                        this.changeFilterValue(filter, null, index)
                    }}
                />
                <DatePicker
                    key={Math.random()}
                    defaultValue={commonProps.defaultValue ? (commonProps.defaultValue.dynamic ? null : commonProps.defaultValue) : null}
                    showToday={operator !== '='}
                    open={this.state['datePickerOpen' + index]}
                    onOpenChange={status => {
                        let obj = {};
                        obj['datePickerOpen' + index] = status;
                        this.setState(obj);
                    }}
                    getCalendarContainer={trigger => {return trigger.parentNode.parentNode}}
                    onChange={(value) => {this.changeFilterValue(filter, value, index)}}
                    renderExtraFooter={operator === '=' ? () => this.generateTimeTags(filter, index, commonProps.defaultValue) : null}
                />
            </div>
        }else if(type === 'categorical') { // 类别
            if(operator === 'include' || operator==='notInclude') { // 包含/不包含
                field = <Input key={Math.random()} { ...commonProps } onBlur={(e) => {
                    this.changeFilterValue(filter, e.target.value, index)
                }} onPressEnter={e => {
                    if(e.target.value !== commonProps.defaultValue) {
                        this.changeFilterValue(filter, e.target.value, index)
                    }
                }}/>
            }else if(operator === 'contain' || operator === 'notContain') { // 包括/不包括
                field = (<Select
                    // key={Math.random()}
                    value={commonProps.defaultValue} // 使用defaultValue不能及时响应全选/取消全选的操作
                    allowClear
                    mode='multiple'
                    maxTagCount={5}
                    showSearch
                    open={dropdownOpen}
                    onDropdownVisibleChange={this.onDropdownVisibleChange}
                    dropdownMatchSelectWidth={false}
                    notFoundContent={fetching ? <Spin size="small" /> : '无'}
                    onSearch={(value) => {this.fetchColumnData(filter, { keyword: value, mandatory: true })}}
                    onFocus={() => {this.fetchColumnData(filter)}}
                    onChange={(value) => {this.changeFilterValue(filter, value, index)}}
                    dropdownRender={menu => (
                        <div>
                            {menu}
                            {columnData.length > 0 && <Divider style={{ margin: '4px 0' }} />}
                            {columnData.length > 0 && <div style={{ padding: '8px', cursor: 'pointer' }}>
                                {/** https://github.com/ant-design/ant-design/issues/13448 */}
                                <span onMouseDown={this.lockClose} onMouseUp={this.lockClose} onClick={() => {
                                    if(commonProps.defaultValue && commonProps.defaultValue.length === columnData.length) {
                                        this.changeFilterValue(filter, [], index)
                                    }else {
                                        this.changeFilterValue(filter, columnData, index)
                                    }
                                    this.setState({ dropdownOpen: false });
                                }}>    
                                    <Icon type={ commonProps.defaultValue && commonProps.defaultValue.length === columnData.length ? 'check-square' : 'border' } /> { commonProps.defaultValue && commonProps.defaultValue.length === columnData.length ? '取消全选' : '全选' }
                                </span>
                            </div>}
                        </div>
                    )}
                >
                    { columnData.map(s => {
                        return <SelectOption key={s} value={s}>{s}</SelectOption>
                    }) }
                </Select>)
            }else { // 等于/不等于
                field = (<Select
                    key={key}
                    { ...commonProps }
                    allowClear
                    mode='single'
                    showSearch
                    dropdownMatchSelectWidth={false}
                    notFoundContent={fetching ? <Spin size="small" /> : '无'}
                    onSearch={(value) => {this.fetchColumnData(filter, { keyword: value, mandatory: true })}}
                    onFocus={() => {this.fetchColumnData(filter)}}
                    onChange={(value) => {this.changeFilterValue(filter, value, index)}}
                >
                    { columnData.map((s, i) => {
                        return <SelectOption key={i} value={s}>{s}</SelectOption>
                    }) }
                </Select>)
            }
        }else {
            field = <Input key={Math.random()} { ...commonProps } onBlur={(e) => {
                if(e.target.value !== commonProps.defaultValue) {
                    this.changeFilterValue(filter, e.target.value, index)
                }
            }} onPressEnter={e => {
                if(e.target.value !== commonProps.defaultValue) {
                    this.changeFilterValue(filter, e.target.value, index)
                }
            }}/> 
        }

        return field;
    }

    lockClose = e => {
        clearTimeout(this.lock);
        this.lock = setTimeout(() => {
          this.lock = null;
        }, 100);
    };

    onDropdownVisibleChange = open => {
        if (this.lock) return;
        this.setState({ dropdownOpen: open });
    };

    changeFilterValue = (filter, value, index) => {
        const { changeFilterValue: propsChangeFilterValue } = this.props;
        filter['value' + index] = value;
        if(propsChangeFilterValue && typeof propsChangeFilterValue === 'function') {
            propsChangeFilterValue({ ...filter });
        }
    }

    fetchColumnData = (filter, options) => {
        const { columnData } = this.state;
        const { keyword, mandatory } = options || {};
        const { combined : isCusMode, dataSource, value1 } = filter;
        let columns;
        if(isCusMode) {
            columns = dataSource.map(d => ({
                id: d.dataSource.code,
                columnName: d.column.name,
                keyword,
            }))
        }
        if(!columnData || columnData.length === 0 || mandatory) {
            this.setState({ columnData: [], fetching: true }, () => {
                const body = isCusMode ? columns : {
                    id: dataSource.code,
                    columnName: filter.name,
                    keyword, 
                };
                service.fetch({
                    url: isCusMode ? URLS.DATASOURCE_QUERY_COLUMNDATA_MUL : URLS.DATASOURCE_QUERY_COLUMNDATA,
                    allow: true,
                    body: body,
                }).then(r => {
                    if(!r.err && r.data.code > 0) {
                        return r;
                    }else {
                        let obj = {};
                        throw obj;
                    }
                }).then(r => {
                    const resData = r.data.data || [];
                    // 需要把已经选择的值作为选项展示出来
                    if(value1) {
                        if(value1 instanceof Array) { // 如果value1是数组
                            value1.forEach(v => {
                                let idx = resData.findIndex(r => r === v);
                                if(idx > -1) {
                                    resData.splice(idx, 1);
                                }
                            });
                            this.setState({
                                columnData: value1.concat(resData),
                                fetching: false
                            });
                        }else {
                            let idx = resData.findIndex(r => r === value1);
                            if(idx > -1) {
                                resData.splice(idx, 1);
                            }
                            this.setState({
                                columnData: [value1].concat(resData),
                                fetching: false
                            });
                        }
                    }else {
                        this.setState({
                            columnData: resData,
                            fetching: false
                        });
                    }
                }).catch(ex => {
                    this.setState({
                        columnData: [],
                        fetching: false
                    });
                    console.error('fetch error', ex);
                });
            });
        }
    }

    render() {
        return this.generatFilter()
    }
}
export default Filter