import React from 'react';
import { config } from './config';
import { getDetail } from './detail';
import { emptyModel } from './_utils/setFormatter';
import { transferAttr } from './_utils/transferAttr';
import { BaseComponentProps, BaseComponentState } from '../interface';

// 此方法为高阶组件,不应再render里面频繁调用,防止频繁实例化,带来性能上的浪费
/*
 *@params(type)  string    组件type
 *@return component
 */
export const getComponent = (type: string) => {
    const NodeObj = config[type] || {};
    const Node = NodeObj.component || null;
    if (!Node) {
        console.error(type + '组件未定义');
        return;
    }
    const setFormat = (columnConfig: any, values: any[]) => {
        const { columnAttrObj, columnType } = columnConfig || {};
        if (!values || values.length <= 0) return undefined;
        const value = values[0] || undefined;
        if (!value) return undefined;
        const transferColumn = transferAttr(columnType, {
            ...(NodeObj.componentAttr || {}),
            ...(columnAttrObj || {}),
        });
        if (NodeObj.setFormatter) return NodeObj.setFormatter(value, transferColumn);
        return value;
    };

    const getFormat = (columnConfig: any, values: any) => {
        const { columnAttrObj, columnType } = columnConfig || {};
        if (!values || !Array.isArray(values) || values.length <= 0) return undefined;
        const newValue = values.filter((item) => {
            return item.value || item.value === 0 || item.label || item.text;
        });
        const transferColumn = transferAttr(columnType, {
            ...(NodeObj.componentAttr || {}),
            ...(columnAttrObj || {}),
        });
        if (NodeObj.getFormatter) {
            return NodeObj.getFormatter(newValue, transferColumn);
        }
        return newValue;
    };
    const com: any = class Base extends React.Component<BaseComponentProps, BaseComponentState> {
        static getDerivedStateFromProps(nextProps: BaseComponentProps, prevState: BaseComponentState) {
            const { prevProps } = prevState;

            let nextState: BaseComponentState = {
                ...prevState,
                prevProps: nextProps,
                columnConfig: nextProps.columnConfig,
                value: getFormat(nextProps.columnConfig, nextProps.value),
            };
            if (JSON.stringify(prevProps.columnConfig) !== JSON.stringify(nextProps.columnConfig)) {
                nextState.columnConfig = nextProps.columnConfig;
            }
            if (JSON.stringify(nextProps.value) !== JSON.stringify(nextProps.value)) {
                nextState.value = getFormat(nextProps.columnConfig, nextProps.value);
            }
            return nextState;
        }
        constructor(props: BaseComponentProps) {
            super(props);
            this.state = {
                prevProps: props,
                value: undefined,
                columnConfig: {},
            };
        }

        onChange = ({ changedValue, isBlur }: any) => {
            const { columnConfig } = this.state;
            const { onChange, changeParams } = this.props;
            let value = setFormat(columnConfig, changedValue);
            // 置空默认逻辑
            if (value && value.length === 0) {
                value = emptyModel;
            }
            if (typeof onChange === 'function') {
                onChange(value);
            }
            if (typeof changeParams === 'function') {
                changeParams({ value, changedValue, isBlur });
            }
        };

        render() {
            const { ...others } = this.props;
            const { columnConfig, value } = this.state;
            const { columnAttrObj, columnType } = columnConfig || {};
            let transferColumn = transferAttr(columnType, {
                ...(NodeObj.componentAttr || {}),
                ...(columnAttrObj || {}),
            });
            const newProps = {
                ...others,
                ...(transferColumn || {}),
            };
            return <Node {...newProps} value={value} onChange={this.onChange} />;
        }
    };
    com.Detail = getDetail(type);
    return com;
};
