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 EllipsisTooltip from '../ellipsisTooltip/index';
import moment from 'moment'
import './filter.less'
const { Option: SelectOption } = Select
const FormItem = Form.Item
const { RangePicker } = DatePicker

class Filter extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            columns: props.columns || [],
            fetching: false,
            columnData: [],
            dropdownOpen: false, // 多选框下拉展开控制
            datePickerOpen1: false, // 时间选择器
            datePickerOpen2: false, // 时间选择器
        }
    }

    generatFilter = () => {
        const { filter } = this.props;
        const { label, type, operator, operatorLabel } = filter;
        
        return <div className='filter'>
            <EllipsisTooltip title={label} style={{ maxWidth: '6.25em' }}>
                <span className='filter-name'>{label}</span>
            </EllipsisTooltip>
            <span className='filter-sep'>{operatorLabel + ' : '}</span>
            <FormItem className='filter-value filter-value1'>
                { this.generateValueItem(filter, 1) }
            </FormItem>
            { operator === 'between' && type !== 'time' && <FormItem className='filter-value filter-value2'>
                { this.generateValueItem(filter, 2) }
            </FormItem> }
        </div>
    }

    generateValueItem = (filter, index) => {
        const { fetching, columnData, dropdownOpen } = this.state;
        let field;
        const { key, type, operator } = filter;
        let defaultValue = type==='time' ? (
            operator === 'between' ? (
                filter['value1'] ? [moment(filter['value1']), moment(filter['value2'])] : null
            ) :
            (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) {
            // 使用随机数作为key以保证每次修改都能重新渲染
            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') {
            if(operator === 'between') {
                field = <RangePicker
                    className='ant-calendar-picker-between'
                    defaultValue={defaultValue}
                    ranges={{
                        '今天': [moment().startOf('day'), moment().endOf('day')],
                        '本月': [moment().startOf('month'), moment().endOf('month')],
                        '上月': [moment().month(moment().month() - 1).startOf('month'), moment().month(moment().month() - 1).endOf('month')],
                        '近半年': [moment().subtract(6, "months").startOf('day'), moment().endOf('day')],
                        '本年': [moment().startOf('year'), moment().endOf('year')],
                        '上年': [moment().subtract(1, "years").startOf('year'), moment().subtract(1, "years").endOf('year')],
                    }}
                    showTime={false}
                    format="YYYY-MM-DD"
                    onChange={values => {
                        this.changeFilterValues(filter, [values[0], values[1]]);
                    }}
                >
                </RangePicker>
            }else {
                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 = {};
                            let inputBox = e.target.getBoundingClientRect();
                            const warpHeight = 379;
                            let bottomY = inputBox.top + inputBox.height + warpHeight + 10;
                            let overH = bottomY - document.body.offsetHeight
                            obj['datePickerOpen' + index] = true;
                            obj[`datePicker${index}-marginTop`] = overH > 0 ? `-${overH}px` : 0;
                            this.setState(obj);
                        }}
                        onChange={() => {
                            // 因为onFocus方法弹出了浮层，onChange方法只在点击清除图标时会调用（相当于不可编辑的input），所以这里只做清除
                            this.changeFilterValue(filter, null, index)
                        }}
                    />
                    <DatePicker
                        key={'datePickerOpen' + index}
                        style={{ marginTop: this.state[`datePicker${index}-marginTop`] }}
                        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) => {
                    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(operator === 'contain' || operator === 'notContain') { // 包括/不包括
                field = (<Select
                    // key={Math.random()} // 这里使用随机数作为key会导致下拉框出现问题
                    value={commonProps.defaultValue} // 使用defaultValue不能及时响应全选/取消全选的操作
                    open={dropdownOpen}
                    onDropdownVisibleChange={this.onDropdownVisibleChange}
                    allowClear
                    mode='multiple'
                    maxTagCount={5}
                    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)}}
                    dropdownRender={menu => (
                        <div>
                            {menu}
                            {columnData.length > 0 && <Divider style={{ margin: '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, i) => {
                        return <SelectOption key={i} value={s}>{s}</SelectOption>
                    }) }
                </Select>)
            }else { // 等于/不等于
                field = (<Select
                    key={key} // 不定义这个key的话每次在box中更新了值后不能正确反映到filter中来
                    { ...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()} 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;
    }

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

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

    changeFilterValues = (filter, values) => {
        const { changeFilterValue: propsChangeFilterValue } = this.props;
        filter['value1'] = values[0];
        filter['value2'] = values[1];
        if(propsChangeFilterValue && typeof propsChangeFilterValue === 'function') {
            propsChangeFilterValue({ ...filter });
        }
    }

    fetchColumnData = (filter, options) => {
        const { keyword, mandatory } = options || {};
        const { code } = this.props;
        const { columnData } = this.state;
        if(!columnData || columnData.length === 0 || mandatory) {
            this.setState({ columnData: [], fetching: true }, () => {
                const body = {
                    id: code,
                    columnName: filter.name,
                    keyword, 
                };
                service.fetch({
                    url: URLS.CHART_QUERY_COLUMNDATA,
                    allow: true,
                    body: body,
                }).then(r => {
                    if(r.code > 0) {
                        return r;
                    }else {
                        let obj = {};
                        throw obj;
                    }
                }).then(r => {
                    const resData = r.data || [];
                    this.setState({
                        columnData: resData.map(d => d || 'null'),
                        fetching: false
                    });
                }).catch(ex => {
                    this.setState({
                        columnData: [],
                        fetching: false
                    });
                    console.error('fetch error', ex);
                });
            });
        }
    }

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