import React from 'react';
import { message, Popover, Modal } from 'antd';
import { config } from './config';
import style from './Cell.less';
import _ from 'lodash';
import { CellProps, CellState } from './interface';
import EditCell from './EditCell';
import FormHelper from '../utils/formHelper';
import insertMenu from '../assets/insertMenu.png';
import copyMenu from '../assets/copyMenu.png';
import extendMenu from '../assets/extendMenu.png';
import delMenu from '../assets/delMenu.png';

export default class Cell extends React.Component<CellProps, CellState> {
    static getDerivedStateFromProps(nextProps: CellProps, prevState: CellState) {
        const { prevProps } = prevState;
        let nextState: CellState = {
            ...prevState,
            prevProps: nextProps,
            editValue: nextProps.cellData,
        };
        if (JSON.stringify(prevProps.cellData) !== JSON.stringify(nextProps.cellData)) {
            nextState.editValue = nextProps.cellData;
        }
        return nextState;
    }
    constructor(props: CellProps) {
        super(props);
        const { cellData } = props;
        this.state = {
            prevProps: props,
            isEditVisible: false,
            isMenuVisible: false,
            editValue: cellData,
            originValue: [],
        };
    }

    handleVisibleChange = (visible: boolean) => {
        if (!visible) {
            this.emitChange();
        }
        this.setState({ isEditVisible: visible, isMenuVisible: false });
    };
    menuVisibleChange = (visible: boolean) => {
        this.setState({ isMenuVisible: visible, isEditVisible: false });
    };
    handleChange = ({ newValue, originValue, emitFlag }: any) => {
        this.setState(
            {
                editValue: newValue,
                originValue,
            },
            () => {
                if (emitFlag) {
                    this.emitChange();
                }
            },
        );
    };

    emitChange = () => {
        let { originValue, editValue } = this.state;
        let { cellData } = this.props;
        if (_.isEqual(cellData, editValue)) {
            return;
        }

        const {
            updateData,
            rowData,
            columnConfig,
            columnConfig: { key },
        } = this.props;
        const extraData = FormHelper.changeTableData({
            item: columnConfig,
            changedKey: key,
            changedValue: editValue,
            originValue,
        });
        extraData.push({
            columnCode: key,
            cellValueList: editValue,
        });
        if (typeof updateData === 'function') {
            updateData({
                rowId: rowData.id,
                value: extraData,
            });
        }
        this.setState({
            editValue: [],
            originValue: [],
        });
    };

    copy = (record: any) => {
        const { showForm } = this.props;
        if (typeof showForm === 'function') {
            showForm({ rowData: record.rowData });
        }
    };

    delData = (record: any) => {
        const { delData, getData, hasGroup, tableId } = this.props;
        // 拆分情况需检查数据是否原始数据
        if (hasGroup) {
            if (record.id === record.groupId) {
                Modal.warning({ title: '删除', content: '不能删除原始拆分数据' });
                return;
            }
        }
        Modal.confirm({
            title: '确认要删除该条数据吗？',
            autoFocusButton: null,
            onOk: async () => {
                const response = await delData({ tableId, data: { id: record.id } });
                if (response && response.success) {
                    message.success('删除成功');
                    if (typeof getData === 'function') {
                        getData({ isClean: true });
                    }
                }
            },
        });
    };

    clickExtraMenu = (menu: any, record: any) => {
        if (menu.check && typeof menu.check === 'function') {
            menu.check({ data: [record] }, this.menuClickFunc.bind(this, menu, record));
        } else {
            this.menuClickFunc(menu, record);
        }
    };

    menuClickFunc = async (menu: any, record: any) => {
        const { flush } = this.props;
        if (typeof menu.onClick === 'function') {
            await menu.onClick({ data: [record], flush });
        }
        if (!menu.noNeedFlush) {
            if (typeof flush === 'function') {
                flush();
            }
        }
    };

    renderPopEdit = ({ columnAttrObj, component }: any) => {
        let { columnConfig, rowData, cellData, columns, tableId } = this.props;
        let { editValue } = this.state;
        return (
            <EditCell
                value={editValue}
                onChange={this.handleChange}
                component={component}
                componentAttr={columnAttrObj}
                columns={columns}
                columnObj={columnConfig}
                columnConfig={columnConfig}
                record={rowData}
                rowData={rowData}
                tableId={tableId}
                rowId={rowData.id}
                cellData={cellData}
            />
        );
    };

    renderPopMenu = () => {
        let { cellData, showForm, extraMenu, noAdd, noDel, hasGroup } = this.props;
        return (
            <div role="presentation" className={style.menuContainer} onClick={this.menuVisibleChange.bind(this, false)}>
                {!noAdd && (
                    <div role="presentation" className={style.menu} onClick={showForm}>
                        <img alt="插入" className={style.menuIcon} src={insertMenu} />
                        <span className={style.menuTitle}>插入</span>
                    </div>
                )}
                {!noAdd && (
                    <div role="presentation" className={style.menu} onClick={this.copy.bind(this, cellData)}>
                        <img alt="复制" className={style.menuIcon} src={copyMenu} />
                        <span className={style.menuTitle}>复制</span>
                    </div>
                )}
                <div role="presentation" className={style.menu} onClick={showForm.bind(this, { rowId: cellData.id })}>
                    <img alt="展开" className={style.menuIcon} src={extendMenu} />
                    <span className={style.menuTitle}>展开</span>
                </div>
                {!noDel && (!hasGroup || (hasGroup && cellData.id !== cellData.groupId)) && (
                    <div role="presentation" className={style.menu} onClick={this.delData.bind(this, cellData)}>
                        <img alt="删除" className={style.menuIcon} src={delMenu} />
                        <span className={style.menuTitle}>删除</span>
                    </div>
                )}
                {extraMenu && extraMenu.length > 0 && (
                    <>
                        <div className={style.splitLine} />
                        {extraMenu.map((item: any, i: number) => {
                            if (typeof item.hidden === 'function' && item.hidden({ record: cellData, menu: item })) {
                                return;
                            }
                            return (
                                <div
                                    key={i}
                                    role="presentation"
                                    className={style.menu}
                                    onClick={this.clickExtraMenu.bind(this, item, cellData)}
                                >
                                    {item.icon &&
                                        (typeof item.icon === 'string' ? (
                                            <img className={style.menuIcon} src={item.icon} alt="" />
                                        ) : (
                                            <span className={style.menuIcon}>{item.icon}</span>
                                        ))}
                                    <span className={style.menuTitle}>{item.label}</span>
                                </div>
                            );
                        })}
                    </>
                )}
            </div>
        );
    };

    renderCellContent = () => {
        let { columnConfig, cellData, noEdit, tableId } = this.props;
        let { isEditVisible, isMenuVisible } = this.state;

        const { readOnlyFlag, columnType } = columnConfig || {};
        let { columnAttrObj } = columnConfig || {};
        if (config[String(columnType)] === undefined) {
            return false;
        }
        columnAttrObj = columnAttrObj || {};
        columnAttrObj.disabled = readOnlyFlag || noEdit || false;
        const { component } = config[String(columnType)];
        return (
            <Popover
                overlayClassName={style.editPop}
                trigger="click"
                visible={isEditVisible}
                onVisibleChange={this.handleVisibleChange}
                content={this.renderPopEdit({ columnAttrObj, component })}
            >
                <Popover
                    overlayClassName={style.menuPop}
                    trigger="contextMenu"
                    visible={isMenuVisible}
                    onVisibleChange={this.menuVisibleChange}
                    placement="rightTop"
                    content={this.renderPopMenu()}
                >
                    <div className={style.cellContent}>
                        <component.Detail value={cellData} columnConfig={columnConfig} tableId={tableId} />
                    </div>
                </Popover>
            </Popover>
        );
    };

    render() {
        const { columnConfig, overlayClassName } = this.props;
        const { width } = columnConfig || {};
        return (
            <div className={overlayClassName ? `${style.cell} ${overlayClassName}` : style.cell} style={{ width }}>
                {this.renderCellContent()}
            </div>
        );
    }
}
