import React from 'react';
import { CompDefault, mergeMeta } from './data-channel';
import _ from 'lodash';
import util from '../common/util';

/**
 * 计算组件初始信息
 */
const calcInitInfo = (props, defaultValue) => {
  let { inputsMeta, outputMeta, meta, ...otherProps } = props;
  const defaultVal = _.cloneDeep(defaultValue);

  // 1.props初始值
  props = { ...defaultVal.props, ...otherProps };

  // 2.state初始值 fixme 这块先不暴露出去
  // const state = defaultValue.state;

  // 3.meta初始值
  meta = mergeMeta({ ...props , inputsMeta, outputMeta, meta }, defaultVal.meta);

  return { ...props, meta };
};

/**
 * 计算内部组件初始信息
 */
const calcInnersInitInfo = (props) => {
  props.meta.inputs?.forEach((item: any) => {
    if (item.tags?.includes('jsx')) {
      if (item.type === 'array') {
        props[item.key] = props[item.key].map((element: any) => {
          element = util.unfreezeProps(element);
          let defaultMap = element.type.defaultMap;
          let type = element.props.type;
          let defaultValue: any;
          if (defaultMap && defaultMap[type]) {
            defaultValue = defaultMap[type];
          } else {
            defaultValue = element.type.default;
          }
          element.info = calcInitInfo(element.props, defaultValue);
          return element;
        });
      } else {
        let element: any = props[item.key];
        element = util.unfreezeProps(element);
        let defaultMap = element.type.defaultMap;
        let type = element.props.type;
        let defaultValue: any;
        if (defaultMap && defaultMap[type]) {
          defaultValue = defaultMap[type];
        } else {
          defaultValue = element.type.default;
        }
        element.info = calcInitInfo(element.props, defaultValue);
        props[item.key] = element;
      }
    }
  });
};

/**
 * 数据链接高阶组件
 */
const connect = (
  Comp: React.FC,
  defaultValue: CompDefault<any, any>,
  defaultValueMap?: any,
): React.FC => {
  const Wrapper: React.FC = (props) => {
    // 1.计算组件初始信息
    props = calcInitInfo(props, defaultValue);

    // 2.计算内部组件初始信息
    calcInnersInitInfo(props);

    // @ts-ignore
    return <Comp {...props} />;
  };
  // @ts-ignore
  Wrapper.default = defaultValue;
  // @ts-ignore
  Wrapper.defaultMap = defaultValueMap;
  return Wrapper;
};

export default connect;
