import { Popover, Button, Checkbox, Empty, Icon } from 'antd';
import { is, fromJS, Map } from 'immutable';
import classname from 'classnames'
import * as React from 'react';
import * as Tool from 'jad-tool'
import { Move } from 'jad-tool'
import { overstepToTooltip, RenderToolTip } from '../Tips/Tips'

const Tools = Tool.extend({
    setCacheData(key: string, value: any[]) {
        window.localStorage.setItem('JG_FilterColumns_Cache_' + key, JSON.stringify(value))
    },
    getCacheData(key: string) {
        var value = window.localStorage.getItem('JG_FilterColumns_Cache_' + key)
        return value ? JSON.parse(value) : false
    },
}, Tool)

// 权重 hasNoRight > required > checked
type ColumnItem = {
    title: string | Function,				//标题
    dataIndex: string,						//index
    group?: string,							//分类组名
    hasNoRight?: boolean,                   // 显示和查看权限， 默认为fasle - 有权限
    required?: boolean,						//是否必选
    checked?: boolean,						//是否选择
}

type FilterColumnsMenuType = {
    title?: string | React.ReactNode;
    style?: any;
    children: React.ReactNode;
    columns: ColumnItem[];
    receivePropsUpdate?: boolean			//接收props是否更新
    onChangeKey?: (key: any[])=> void;		//返回自定义后的dataIndex[]
    initCallback?: boolean;					//初始化后是否需要回调一次,恢复缓存考虑
    cacheKey?: string;
}

const archorKey = 'archor'

//react component
export class FilterColumnsMenu extends React.Component<FilterColumnsMenuType> {
    state = {
        visible: false,
        renderGroupBuff: {},
        checkedBuff: [],
        groupLength: 0,
        init: false,
        activeKey: '',
        moveFlag: false,
    }
    doNotDisplayGroup = {}
    archorKeyRefsMap = {}


    componentDidMount() {
        const { columns, cacheKey, receivePropsUpdate } = this.props;
        const cacheData = this.replaceColumnsCacheTitle(Tools.getCacheData(cacheKey), columns);
        // 页面首载或重载时，要对比前后this.props传入的columns是否有变化，若有，应该取columns
        if (!cacheKey || !cacheData || (!this.compareColumnsCacheData(columns, cacheData) && receivePropsUpdate)) {
            this.init(columns);
        } else {
            this.init(cacheData);
        }
    }
    private replaceColumnsCacheTitle(cacheData, columns) {
        if (!cacheData) return cacheData
        return cacheData.map(obj => {
            /**
             * 1. 如果缓存的title不存在(函数时)
             * 2. 或者缓存的title是个对象（reactNode等）时可能与columns的title不全等
             * 3. 或者因为需求改动，原来的title字段内容更新了
             * 以上等原因，需要将缓存的title替换为props columns的title
             */
            let item = columns.find(item => obj['dataIndex'] === item['dataIndex'])
            obj['title'] = item ? item['title'] : obj['title']
            return obj
        })
    }
    private compareColumnsCacheData(columns, cacheData) {
        const copyColumns = fromJS(columns);
        const newCopyColumns = copyColumns.map(val => Map({
            dataIndex: val.get('dataIndex'),
            group: val.get('group'),
            hasNoRight: val.get('hasNoRight'),
            required: val.get('required'),
        })); // 只有这些才是自定义table真正需要比较的
        const copyCacheData = fromJS(cacheData);
        const newCopyCacheData = copyCacheData.map(val => Map({
            dataIndex: val.get('dataIndex'),
            group: val.get('group'),
            hasNoRight: val.get('hasNoRight'),
            required: val.get('required'),
        }));
        return is(newCopyColumns, newCopyCacheData)
    }
    UNSAFE_componentWillReceiveProps(nextProps) {
        if (!this.state.init) return;
        const { receivePropsUpdate } = this.props;
        const { groupLength: oldGroupLength } = this.state;
        if (oldGroupLength === 0 && receivePropsUpdate) {
            console.warn('FilterColumnsMenu->receivePropsUpdate在更新columns的时候,检测到origin columns为空,请确保初始columns在初始化的时候被赋值')
        }
    }

    private init(columnsBuff: any[]) {
        const { initCallback } = this.props;
        let renderGroupBuff = {}
        const groupLength = columnsBuff.length;
        let checkedBuff = columnsBuff.map(e => {
            let item = Object.assign({}, e)	//防止引用类型穿透
            let groupName = item.group || '其他'
            item.required = item.hasNoRight ? false : item.required; // 无权限则非必须
            item.checked = item.hasNoRight ? false : (Tool.isExist(item.checked) ? item.checked : true); // 无权限则不选中，item.checked 未主动赋值时默认值为 true
            item.group = groupName;
            let group = renderGroupBuff[groupName] || []
            renderGroupBuff[groupName] = group
            group.push(item)
            return item
        }).filter(item => {
            if (item.required || item.checked) {
                return item
            }
        })
        this.setState({
            renderGroupBuff,
            checkedBuff,
            groupLength,
            init: true
        }, () => {
            if (initCallback) {
                this.onHandleOk()
            }
        })
    }

    private onHandleClear(allClear, target) {
        let { renderGroupBuff, checkedBuff } = this.state
        if (allClear) {
            for (let key in renderGroupBuff) {
                renderGroupBuff[key] = renderGroupBuff[key].map(item => {
                    if (!item.required) { // 必选的不能操作
                        item.checked = false;
                    }
                    return item
                })
            }
            checkedBuff = [];
        } else {
            var groupName = target.group || '其他'
            var dataIndex = target.dataIndex
            renderGroupBuff[groupName] = renderGroupBuff[groupName].map(item => {
                if (item.dataIndex === dataIndex && !item.required) { // 必选的不能操作
                    item.checked = false;
                }
                return item
            })
            checkedBuff = checkedBuff.filter(e => e.dataIndex !== dataIndex)
        }
        this.setState({
            renderGroupBuff,
            checkedBuff
        }, () => {
            this.onHandleOk()
        })
    }

    private onHandleChecked(checkData, target) {
        let { renderGroupBuff } = this.state
        let checked = target.target.checked
        // all Check
        if (Tools.isArray(checkData)) {
            var groupName = checkData[0].group
            renderGroupBuff[groupName] = renderGroupBuff[groupName].map(item => {
                if (!item.required) { // 必选的不能操作
                    item.checked = checked;
                }
                return item
            })
        } else {
            var groupName = checkData.group
            var dataIndex = checkData.dataIndex
            renderGroupBuff[groupName] = renderGroupBuff[groupName].map(item => {
                if (item.dataIndex === dataIndex) {
                    item.checked = checked;
                }
                return item
            })
        }
        this.setState({
            renderGroupBuff
        })
        this.onHandleOk()
    }

    private onHandleOk() {
        const { onChangeKey, cacheKey, columns } = this.props;
        const { renderGroupBuff } = this.state;
        var filterBuff = []
        for (let key in renderGroupBuff) {
            renderGroupBuff[key].map(item => { filterBuff[item.dataIndex] = item; return item })
        }
        let newColumsCache = columns.map((e) => {
            let item = Object.assign({}, e)//防止引用类型穿透
            item.checked = filterBuff[item.dataIndex] ? filterBuff[item.dataIndex].checked : item.checked
            return item
        })
        let checkedBuff = newColumsCache.filter(item => {
            if ((item.required || item.checked) && !item.hasNoRight) {
                return item
            }
        })
        this.setState({
            checkedBuff,
        })
        //update cache
        if (!Tool.isEmptyArray(newColumsCache)) {
            Tools.setCacheData(cacheKey, newColumsCache)
        }
        //return [dataIndex(string),...]
        if (onChangeKey && Tools.isFunction(onChangeKey)) {
            var resultKey = checkedBuff.map(e => e.dataIndex)
            onChangeKey(resultKey)
        }
        return false;
    }

    private onHandleVisibleChange(visible) {
        this.setState({
            visible
        })
    }

    private onHandleAnchorScroll(targetKey) {
        const { moveFlag } = this.state
        if (moveFlag) {
            return false;
        }
        if (!this.archorKeyRefsMap[archorKey] || !this.archorKeyRefsMap[targetKey]) {
            console.error('FilterColumnsMenu->archor 暂未渲染完毕')
            return false;
        }
        const container: any = this.archorKeyRefsMap[archorKey]
        const target: any = this.archorKeyRefsMap[targetKey]
        var distance = 40
        var minScroll = 50;
        var maxScroll = container.scrollHeight - container.clientHeight;
        var offsetTop = target.offsetTop
        var scroll = offsetTop - distance
        if (scroll < minScroll) {
            scroll = 0
        }
        if (scroll > maxScroll) {
            scroll = maxScroll
        }
        this.setState({
            moveFlag: true
        })
        var m = new Move()
        m.ease([container.scrollTop, scroll], 500, function (v) {
            container.scrollTo(0, v)
        }, () => {
            setTimeout(() => {
                this.setState({
                    moveFlag: false
                })
            }, 100)
        })
    }


    private renderGroupItem(groupName, groupData, index) {
        const { activeKey } = this.state
        let checkedAll = false; //是否全选中
        checkedAll = groupData.every((obj) => obj.required || obj.checked || obj.hasNoRight);
        return (
            <div ref={(ref) => this.archorKeyRefsMap[archorKey + index] = ref} className='jad-filtercolumsmenu-group-container' key={groupName}>
                <p className={'label'}>
                    <label className={classname('name', activeKey === groupName ? 'active' : '')} > {overstepToTooltip(groupName, 6)} </label>
                    <span className={'checkBox'}>
                        <Checkbox checked={checkedAll} onChange={event => this.onHandleChecked(groupData, event)}>全选</Checkbox>
                    </span>
                </p>
                <div className={'content'}>
                    {
                        groupData.map((item, index) => {
                            if (item.hasNoRight) { // 无权限则不展示
                                return null
                            }
                            return (
                                <Checkbox
                                    key={item.dataIndex}
                                    checked={item.required || item.checked} // 必选必须选中，且不能操作
                                    disabled={item.required}
                                    onChange={event => this.onHandleChecked(item, event)}
                                >
                                    {Tools.isFunction(item.title) ? item.title() : RenderToolTip(item.title, 6)}
                                </Checkbox>
                            )
                        })
                    }
                </div>
            </div>
        )
    }

    private renderGroup() {
        const { renderGroupBuff, moveFlag, activeKey } = this.state
        if (Tool.isEmptyObject(renderGroupBuff)) {
            return <Empty />
        }
        //这里之前存在问题keys是无序列的
        return <div
            ref={(ref) => this.archorKeyRefsMap[archorKey] = ref}
            className={classname('jad-filtercolumsmenu-container-content', 'group')}
            onScroll={() => {
                if (!moveFlag && activeKey !== '') {
                    this.setState({ activeKey: '' })
                }
            }}
        >
            {
                Object.keys(renderGroupBuff).map((key, index) => {
                    var group = renderGroupBuff[key];
                    let doNotDisplay = false; // 是否不展示
                    doNotDisplay = group.every((obj) => obj.hasNoRight);
                    if (doNotDisplay) {
                        const { doNotDisplayGroup } = this;
                        this.doNotDisplayGroup = { ...doNotDisplayGroup, [key]: key }
                        return
                    }
                    return this.renderGroupItem(key, group, index)
                })
            }
        </div>
    }

    private renderAnchor() {
        const { renderGroupBuff, activeKey } = this.state
        const classStyle = classname(
            'jad-filtercolumsmenu-container-content',
            'anchor',
            'jad-filtercolumsmenu-anchor-container'
        )
        return <div className={classStyle}>
            {
                Object.keys(renderGroupBuff).map((key, index) => {
                    if (this.doNotDisplayGroup[key]) return;
                    return <a className={activeKey === key ? 'active' : ''} onClick={() => {
                        this.setState({ activeKey: key })
                        this.onHandleAnchorScroll(archorKey + index)
                    }} key={key}>
                        {overstepToTooltip(key, 6)}
                    </a>
                })
            }
        </div>
    }

    private renderCheck() {
        const { checkedBuff } = this.state;
        return <ul className={'jad-filtercolumsmenu-checked-container'}>
            {
                checkedBuff.map(e => {
                    if (e.hasNoRight) { // 无权限则不展示
                        return null;
                    }
                    return <li key={e.dataIndex}>
                        {Tools.isFunction(e.title) ? e.title() : e.title}
                        {/* 必选的不能删除 */}
                        {!e.required ? <Icon onClick={() => this.onHandleClear(false, e)} style={{ float: 'right', marginTop: '2px' }} type="close" /> : null}
                    </li>
                })
            }
        </ul>;
    }

    private renderContent() {
        const { checkedBuff } = this.state
        return (
            <React.Fragment>
                <div className={'jad-filtercolumsmenu-group-wrap'}>
                    <div className={classname('jad-filtercolumsmenu-container-wrap', 'add')}>
                        <h3>可添加的列</h3>
                        {this.renderAnchor()}
                        {this.renderGroup()}
                    </div>
                    <div className={classname('jad-filtercolumsmenu-container-wrap', 'checked')}>
                        <h3>已选{checkedBuff.length}列<a onClick={() => this.onHandleClear(true, null)}>清空全部</a></h3>
                        {this.renderCheck()}
                    </div>
                </div>
            </React.Fragment>
        )
    }

    private renderTitle() {
        const {
            title,
        } = this.props
        return (
            <p className={'jad-filtercolumsmenu-title-container'}>
                {title ? title : '自定义列'}
            </p>
        )
    }


    //render filter component groud
    public render() {
        const { children, style } = this.props
        const { visible } = this.state
        return (
            <Popover
                placement={'bottomRight'}
                trigger={'click'}
                overlayClassName={'jad-filtercolumsmenu-container'}
                title={this.renderTitle()}
                content={this.renderContent()}
                visible={visible}
                overlayStyle={style}
                onVisibleChange={this.onHandleVisibleChange.bind(this)}
            >
                {children}
            </Popover>
        )
    }
}
