import React from 'react';
import {FormItem, FormControlProps, FormBaseControl} from './Item';
import {evalJS, filter} from '../../utils/tpl';
import {isObjectShallowModified} from '../../utils/helper';

/**
 * 公式功能控件。
 * 文档：https://baidu.gitee.io/amis/docs/components/form/formula
 */
export interface FormulaControlSchema extends FormBaseControl {
  /**
   * 指定为公式功能控件。
   */
  type: 'formula';

  /**
   * 当某个按钮的目标指定为此值后，会触发一次公式应用。这个机制可以在 autoSet 为 false 时用来手动触发
   */
  id?: string;

  /**
   * 触发公式的作用条件，如 data.xxx == \"a\" 或者 ${xx}
   */
  condition?: string;

  /**
   * 是否自动应用
   */
  autoSet?: boolean;

  /**
   * 公式
   */
  formula?: string;

  /**
   * 是否初始应用
   */
  initSet?: boolean;

  /**
   * 字段名，公式结果将作用到此处指定的变量中去
   */
  name?: string;
}

export interface FormulaProps
  extends FormControlProps,
    Omit<
      FormulaControlSchema,
      'type' | 'className' | 'descriptionClassName' | 'inputClassName'
    > {}

export default class FormulaControl extends React.Component<
  FormControlProps,
  any
> {
  componentDidMount() {
    const {formula, data, setPrinstineValue, initSet, condition} = this.props;

    if (!formula || initSet === false) {
      return;
    } else if (
      condition &&
      !~condition.indexOf('$') &&
      !~condition.indexOf('<%') &&
      !evalJS(condition, data as object)
    ) {
      return;
    }

    const result: any = evalJS(formula, data as object);
    result !== null && setPrinstineValue(result);
  }

  componentWillReceiveProps(nextProps: FormControlProps) {
    const {formula, data, onChange, autoSet, value, condition} = this.props;

    if (
      autoSet !== false &&
      formula &&
      nextProps.formula &&
      isObjectShallowModified(data, nextProps.data, false) &&
      value === nextProps.value
    ) {
      const nextResult: any = evalJS(
        nextProps.formula,
        nextProps.data as object
      );

      if (condition && nextProps.condition) {
        if (!!~condition.indexOf('$') || !!~condition.indexOf('<%')) {
          // 使用${xxx}，来监听某个变量的变化
          if (
            filter(condition, data) !==
            filter(nextProps.condition, nextProps.data)
          ) {
            onChange(nextResult);
          }
        } else if (evalJS(nextProps.condition, nextProps.data as object)) {
          // 使用 data.xxx == 'a' 表达式形式来判断
          onChange(nextResult);
        }
      } else {
        const prevResult: any = evalJS(formula, data as object);
        if (JSON.stringify(prevResult) !== JSON.stringify(nextResult)) {
          onChange(nextResult ?? '');
        }
      }
    }
  }

  doAction() {
    // 不细化具体是啥动作了，先重新计算，并把值运用上。

    const {formula, data, onChange, autoSet, value} = this.props;

    const result: any = evalJS(formula, data as object);
    onChange(result);
  }

  render() {
    return null;
  }
}

@FormItem({
  type: 'formula',
  wrap: false,
  strictMode: false,
  sizeMutable: false
})
export class FormulaControlRenderer extends FormulaControl {}
