
import React from 'react';
import { Button, Checkbox, Popover, Select, Slider } from 'kts-components-antd-x4';
import { ColumnTitle } from 'kts-components-antd-x4/lib/table/interface';
import { SortableContainer, SortableElement, SortableHandle } from 'react-sortable-hoc';
import { MenuOutlined } from '@ant-design/icons';
import { arrayMoveImmutable } from 'array-move';
import IColumnType from '../interfaces/IColumnType';
import './index.less';

export interface ISortItem {

    /** 字段标记 */
    key: React.Key;

    /** 是否启用 */
    checked: boolean;
}

export interface ISortProps {

    /** 孩子 */
    children?: React.ReactNode;

    /** 元数据 */
    columns?: IColumnType[];

    /** 筛选后的Key */
    dataSource?: ISortItem[];

    /** 必须显示的字段 */
    mustShows?: React.Key[];

    /** 更新变化 */
    onChange?: (e: ISortItem[]) => void;
}

export default class Sort extends React.Component<ISortProps>{

    /** 筛选 columns */
    static filter = (columns?: IColumnType[], dataSource?: ISortItem[]) => {
        const map = new Map()
        columns?.forEach(e => { map.set(e.key, e) })
        return dataSource?.filter(e => e.checked).map(e => map.get(e.key)) ?? columns
    }

    render() {
        return <Main {...this.props} />
    }
}

function Main(props: ISortProps) {

    const [visible, setVisible] = React.useState(false)

    const content = React.useMemo(() => {
        return (
            <SortableComponent {...props} visible={visible} setVisible={setVisible} />
        )
    }, [props, visible])

    return (
        <Popover
            trigger="click"
            content={content}
            placement="bottomRight"
            visible={visible}
            overlayClassName='kts-xui-metadata-sort-popover'
            onVisibleChange={setVisible}
        >
            {props.children}
        </Popover>
    )
};

const DragHandle = SortableHandle(() => <MenuOutlined style={{ color: '#AFAFAF', cursor: 'grab', fontWeight: 'bold' }} />);

const SortableItem = SortableElement(props => {
    return (
        <li className='kts-xui-metadata-sort-li' >
            <div style={{ flex: 1 }}>
                <Checkbox
                    disabled={props.mustShow}
                    checked={props.mustShow || props.value.checked}
                    onChange={e => {
                        props.setDataSource(s => {
                            props.value.checked = e.target.checked;
                            return [...s];
                        })
                    }}
                >
                    {props.value.title}
                </Checkbox>
            </div>
            <div className='kts-xui-metadata-sort-li-drag' ><DragHandle /></div>
        </li>
    )
});

const SortableList = SortableContainer(({ items, ...props }) => {
    return (
        <ul className='kts-xui-metadata-sort-ul' >
            {items.map((value, index) => {
                const mustShow = (props.mustShows || []).indexOf(value.key) >= 0;
                return <SortableItem key={index} index={index} value={value} mustShow={mustShow} {...props} />
            })}
        </ul>
    );
});

function SortableComponent(props: ISortProps & { visible: boolean, setVisible: (e: boolean) => void }) {

    const initDataSource = React.useCallback(() => {
        const columnsMap = (() => {
            const map = new Map<React.Key, IColumnType>()
            props.columns?.forEach(e => { map.set(e.key, e) })
            return map;
        })()

        const dataSource = props.dataSource?.filter(e => columnsMap.has(e.key)).map(e => ({ ...e, title: columnsMap.get(e.key)?.title })) ?? [];

        const dataSourceMap = (() => {
            const map = new Map<React.Key, ISortItem & { title: ColumnTitle<any> }>()
            dataSource.forEach(e => { map.set(e.key, e) })
            return map;
        })()

        const columns = props.columns?.filter(e => !dataSourceMap.has(e.key)).map(e => ({ key: e.key, checked: false, title: e.title })) ?? []

        return [...dataSource, ...columns];
    }, [props.columns, props.dataSource])

    const [dataSource, setDataSource] = React.useState<(ISortItem & { title: ColumnTitle<any> })[]>(initDataSource);

    const onSortEnd = React.useCallback(({ oldIndex, newIndex }) => {
        setDataSource(s => {
            const newS = arrayMoveImmutable(s, oldIndex, newIndex);
            return newS;
        })
    }, [])

    const onSave = React.useCallback(() => {
        props.onChange && props.onChange(dataSource.map(e => ({ ...e, title: undefined })));
        props.setVisible(false);
    }, [dataSource])

    const onCancel = React.useCallback(() => {
        props.setVisible(false);
    }, [initDataSource])

    const onReplyDefault = React.useCallback(() => {
        props.onChange && props.onChange(props.columns?.map(e => ({ key: e.key, checked: true })) ?? []);
        props.setVisible(false);
    }, [props.columns])

    React.useEffect(() => {
        props.visible && setDataSource(initDataSource);
    }, [initDataSource, props.visible])

    React.useEffect(() => {
        if (!props.dataSource) {
            props.onChange && props.onChange(props.columns?.map(e => ({ key: e.key, checked: true })) ?? []);
        }
    }, [props.dataSource])

    return (
        <div style={{ padding: '12px 0' }} >
            <SortableList
                useDragHandle
                disableAutoscroll
                items={dataSource}
                onSortEnd={onSortEnd}
                setDataSource={setDataSource}
                mustShows={props.mustShows}
            />
            <div className='kts-xui-metadata-sort-button-list' >
                <Button type="link" onClick={onSave} >保存</Button>
                <Button type="link" onClick={onCancel} >取消</Button>
                <div style={{ flex: 1, height: 5 }} ></div>
                <Button type="link" onClick={onReplyDefault} >恢复默认</Button>
            </div>
        </div>
    );
}