import React from 'react';
import { ScopedContext, IScopedContext } from '../Scoped';
import { Renderer, RendererProps } from '../factory';
import { SchemaNode, Schema, Action } from '../types';
import { filter } from '../utils/tpl';
import Modal from '../components/Modal';
import findLast from 'lodash/findLast';
import {
  guid,
  isVisible,
  autobind,
  isMobile,
  isObjectShallowModified
} from '../utils/helper';
import { reaction } from 'mobx';
import { Icon } from '../components/icons';
import { ModalStore, IModalStore } from '../store/modal';
import { findDOMNode } from 'react-dom';
import { Spinner } from '../components';
import { IServiceStore } from '../store/service';
import {
  BaseSchema,
  SchemaClassName,
  SchemaCollection,
  SchemaName,
  SchemaTpl
} from '../Schema';
import { ActionSchema } from './Action';
import { isAlive } from 'mobx-state-tree';
import { tokenize } from '../utils/tpl-builtin';

/**
 * Dialog 弹框渲染器。
 * 文档：https://baidu.gitee.io/amis/docs/components/dialog
 */
export interface DialogSchema extends BaseSchema {
  type: 'dialog';

  /**
   * 默认不用填写，自动会创建确认和取消按钮。
   */
  actions?: Array<ActionSchema>;

  /**
   * 内容区域
   */
  body?: SchemaCollection;

  /**
   * 配置 Body 容器 className
   */
  bodyClassName?: SchemaClassName;

  /**
   * 是否支持按 ESC 关闭 Dialog
   */
  closeOnEsc?: boolean;

  /**
   * 是否支持点其它区域关闭 Dialog
   */
  closeOnOutside?: boolean;

  name?: SchemaName;

  /**
   * Dialog 大小
   */
  size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'full';

  /**
   * 请通过配置 title 设置标题
   */
  title?: SchemaCollection;

  header?: SchemaCollection;
  headerClassName?: SchemaClassName;

  footer?: SchemaCollection;

  /**
   * 影响自动生成的按钮，如果自己配置了按钮这个配置无效。
   */
  confirm?: boolean;

  /**
   * 是否显示关闭按钮
   */
  showCloseButton?: boolean;

  /**
   * 是否显示错误信息
   */
  showErrorMsg?: boolean;
  /**
   * 父容器id
   */
  containerId?: string;
  /**
   * 是否显示蒙层
   */
  overlay?: boolean;
}

export type DialogSchemaBase = Omit<DialogSchema, 'type'>;

export interface DialogProps extends RendererProps, Omit<DialogSchema, 'className'> {
  onClose: (confirmed?: boolean, formInstance?: any, tableInstance?: any) => void;
  onConfirm: (
    values: Array<object>,
    action: Action,
    ctx: object,
    targets: Array<any>,
    tableInstance?: any
  ) => void;
  children?: React.ReactNode | ((props?: any) => React.ReactNode);
  store: IModalStore;
  show?: boolean;
  lazyRender?: boolean;
  lazySchema?: (props: DialogProps) => SchemaCollection;
  wrapperComponent: React.ElementType;
}

export default class Dialog extends React.Component<DialogProps> {
  static propsList: Array<string> = [
    'title',
    'size',
    'closeOnEsc',
    'closeOnOutside',
    'children',
    'bodyClassName',
    'headerClassName',
    'confirm',
    'onClose',
    'onConfirm',
    'show',
    'body',
    'showCloseButton',
    'showErrorMsg',
    'actions',
    'popOverContainer'
  ];
  static defaultProps = {
    title: '弹框',
    bodyClassName: '',
    confirm: true,
    show: true,
    lazyRender: false,
    showCloseButton: true,
    wrapperComponent: Modal,
    closeOnEsc: false,
    closeOnOutside: false,
    showErrorMsg: true,
    overlay: true,
  };

  reaction: any;
  isDead = false;
  $$id: string = guid();
  topDialog: boolean //顶部弹窗
  // Jay
  formInstance: any; // 获取dialog里的form实例
  tableInstance: any
  formStoreInputData: any;
  state = {
    minWin: false
  }
  constructor(props: DialogProps) {
    super(props);
    if (window['localDialgoData']) {
      this.topDialog = !window['localDialgoData'].hasUse && window['localDialgoData'].scheme?.type === 'dialog'
      // 保证只有第一个弹窗打开的才有这个属性并且能获取到
      window['localDialgoData'].hasUse = true
    }
    this.state = {
      minWin: false
    }
    if (this.topDialog && this.props.title) {
      document.title = filter(this.props.translate(this.props.title), this.props.data)
    }

    props.store.setEntered(!!props.show);
    this.handleSelfClose = this.handleSelfClose.bind(this);
    this.handleAction = this.handleAction.bind(this);
    this.handleDialogConfirm = this.handleDialogConfirm.bind(this);
    this.handleDialogClose = this.handleDialogClose.bind(this);
    this.handleDrawerConfirm = this.handleDrawerConfirm.bind(this);
    this.handleDrawerClose = this.handleDrawerClose.bind(this);
    this.handleEntered = this.handleEntered.bind(this);
    this.handleExited = this.handleExited.bind(this);
    this.handleFormInit = this.handleFormInit.bind(this);
    this.handleFormSaved = this.handleFormSaved.bind(this);
    this.handleFormChange = this.handleFormChange.bind(this);
    this.handleChildFinished = this.handleChildFinished.bind(this);

    const store = props.store;
    this.reaction = reaction(
      () => `${store.loading}${store.error}`,
      () => this.forceUpdate()
    );
  }

  // shouldComponentUpdate(nextProps:DialogProps, nextState:DialogState) {
  //     const props = this.props;

  //     if (this.state.entered !== nextState.entered) {
  //         return true;
  //     } else if (props.show === nextProps.show && !nextProps.show) {
  //         return false;
  //     }

  //     return isObjectShallowModified(this.props, nextProps);
  // }

  componentWillUnmount() {
    delete this.formInstance
    delete this.tableInstance
    delete this.formStoreInputData
    this.reaction && this.reaction();
    this.isDead = true;
  }

  buildActions(): Array<ActionSchema> {
    const { actions, confirm, translate: __ } = this.props;

    if (typeof actions !== 'undefined') {
      return actions;
    }

    let ret: Array<ActionSchema> = [];
    ret.push({
      type: 'button',
      actionType: 'cancel',
      label: __('cancel')
    });

    if (confirm) {
      ret.push({
        type: 'button',
        actionType: 'confirm',
        label: __('confirm'),
        primary: true
      });
    }

    return ret;
  }

  handleSelfClose(e?: any, confirmed?: boolean) {
    const { onClose, store } = this.props;
    const _formInstance = this.formInstance
    const _tableInstance = this.tableInstance
    delete this.formInstance
    delete this.tableInstance
    delete this.formStoreInputData
    // clear error
    store.updateMessage();
    if (onClose) {
      onClose(confirmed, _formInstance, _tableInstance); // Jay
      // 如果是顶层弹窗 关闭直接把页码关闭
    } else if (location.hash.includes('blank/dialogView') && this.topDialog) {
      window.close()
    }
  }

  handleSelfMin = (e?: any, confirmed?: boolean) => {
    this.setState({ minWin: true })
  }

  handleAction(e: React.UIEvent<any>, action: Action, data: object) {
    const { store, onAction } = this.props;

    if (action.type === 'reset') {
      store.reset();
    } else if (action.actionType === 'cancel') {
      this.handleSelfClose();
    } else if (onAction) {
      onAction(e, action, data);
    }
  }

  handleDialogConfirm(values: object[], action: Action, ...args: Array<any>) {
    const { store } = this.props;

    if (action.mergeData && values.length === 1 && values[0]) {
      store.updateData(values[0]);
    }

    const dialog = store.action.dialog as any;

    if (
      dialog &&
      dialog.onConfirm &&
      dialog.onConfirm(values, action, ...args) === false
    ) {
      return;
    }

    store.closeDialog(true);
  }

  handleDialogClose(...args: Array<any>) {
    const { store } = this.props;

    const action = store.action as Action;
    const dialog = action.dialog as any;

    if (dialog.onClose && dialog.onClose(...args) === false) {
      return;
    }

    store.closeDialog(args[1]);
  }

  handleDrawerConfirm(values: object[], action: Action, ...args: Array<any>) {
    const { store } = this.props;

    if (action.mergeData && values.length === 1 && values[0]) {
      store.updateData(values[0]);
    }

    const drawer = store.action.drawer as any;

    if (
      drawer &&
      drawer.onConfirm &&
      drawer.onConfirm(values, action, ...args) === false
    ) {
      return;
    }

    store.closeDrawer();
  }

  handleDrawerClose(...args: Array<any>) {
    const { store } = this.props;

    const action = store.action as Action;
    const drawer = action.drawer as any;

    if (drawer.onClose && drawer.onClose(...args) === false) {
      return;
    }

    store.closeDrawer();
  }

  handleEntered() {
    const { lazySchema, store } = this.props;

    store.setEntered(true);
    if (typeof lazySchema === 'function') {
      store.setSchema(lazySchema(this.props));
    }

    const activeElem = document.activeElement as HTMLElement;
    if (activeElem) {
      const dom = findDOMNode(this) as HTMLElement;
      dom && !dom.contains(activeElem) && activeElem.blur();
    }
  }

  handleExited() {
    const { lazySchema, store } = this.props;
    if (isAlive(store)) {
      store.reset();
      store.setEntered(false);
      if (typeof lazySchema === 'function') {
        store.setSchema('');
      }
    }
  }

  handleFormInit(data: any) {
    const { store } = this.props;

    store.setFormData(data);
  }

  handleFormChange(data: any, name?: string) {
    const { store } = this.props;
    // 如果 dialog 里面不放 form，而是直接放表单项就会进到这里来。

    if (typeof name === 'string') {
      data = {
        ...store.formData,
        [name]: data,
      };
    }
    if (this.formStoreInputData) {
      data = {
        ...data,
        ...this.formStoreInputData
      };
    }
    store.setFormData(data);
  }

  handleFormSaved(data: any, response: any) {
    const { store } = this.props;
    store.setFormData({
      ...data,
      ...response
    });
  }

  handleChildFinished(value: any, action: Action) {
    // 下面会覆盖
  }

  openFeedback(dialog: any, ctx: any) {
    return new Promise(resolve => {
      const { store } = this.props;
      store.setCurrentAction({
        type: 'button',
        actionType: 'dialog',
        dialog: dialog
      });
      store.openDialog(ctx, undefined, confirmed => {
        resolve(confirmed);
      });
    });
  }

  @autobind
  getPopOverContainer() {
    return (findDOMNode(this) as HTMLElement).querySelector(
      `.${this.props.classPrefix}Modal-content`
    );
  }

  renderBody(body: SchemaNode, key?: any): React.ReactNode {
    let { render, store, actions, data } = this.props;
    const dialogTitle = tokenize(typeof this.props.title == 'string' ? this.props.title : '', data)

    if (Array.isArray(body)) {
      return body.map((body, key) => this.renderBody(body, key));
    }

    let subProps: any = {
      key,
      disabled: (body && (body as any).disabled) || store.loading,
      onAction: this.handleAction,
      onFinished: this.handleChildFinished,
      popOverContainer: this.getPopOverContainer,
      affixOffsetTop: 0,
      onChange: this.handleFormChange,
      onInit: this.handleFormInit,
      onSaved: this.handleFormSaved,
      syncLocation: false, // 弹框中的 crud 一般不需要同步地址栏
      // Jay 将dialog关闭方法下发
      onDialogClose: this.props.onClose,
      getFormInstance: (form: any) => {
        if (!this.formInstance) this.formInstance = form
      },
      getFormStore: (data: any) => {
        this.formStoreInputData = data
      },
      onFormChange: actions?.some(action => action.confirmApi != undefined) ? this.handleFormChange : undefined,
      inModal: true,
      dialogTitle
    };

    if (!(body as Schema).type) {
      return render(`body${key ? `/${key}` : ''}`, body, subProps);
    }

    let schema: Schema = body as Schema;

    if (schema.type === 'form') {
      schema = {
        mode: 'horizontal',
        wrapWithPanel: false,
        submitText: null,
        ...schema
      };
    }

    return render(`body${key ? `/${key}` : ''}`, schema, subProps);
  }
  setLoading(loading: boolean) {
    this.props.store.markFetching(loading);
  }

  renderFooter() {
    const actions = this.buildActions();

    if (!actions || !actions.length) {
      return null;
    }

    const { store, render, classnames: cx, showErrorMsg, replace } = this.props;

    return (
      <div className={cx('Modal-footer')}>
        {/* aug 错误提示在移动端展示效果不好，反正其他地方也有，就不展示了 */}
        {isMobile() && (store.loading || store.error) ? (
          <div className={cx('Dialog-info')} key="info">
            <Spinner size="sm" key="info" show={store.loading} />
            {store.error && showErrorMsg !== false ? (
              <span className={cx('Dialog-error')}>{store.msg}</span>
            ) : null}
          </div>
        ) : null}
        {actions.map((action, key) =>
          render(`action/${key}`, action, {
            replace,
            handleSendAction: this.formInstance?.handleSendAction,
            data: store.formData,
            onAction: this.handleAction,
            key,
            disabled: action.disabled || store.loading,
            setLoading: this.setLoading.bind(this)
          })
        )}
      </div>
    );
  }

  render() {
    const store = this.props.store;
    const {
      className,
      size,
      closeOnEsc,
      closeOnOutside,
      title,
      render,
      header,
      body,
      bodyClassName,
      headerClassName,
      show,
      lazyRender,
      lazySchema,
      wrapperComponent,
      showCloseButton,
      containerId,
      env,
      classnames: cx,
      classPrefix,
      translate: __,
      overlay
    } = {
      ...this.props,
      ...store.schema
    } as any;

    const Wrapper = wrapperComponent || Modal;
    // {this.state.minWin ? <div onClick={() => this.setState({ minWin: false })} style={{ border: '1px solid', position: 'fixed', top: 0, right: 0 }}>{filter(this.props.translate(this.props.title), this.props.data)} <span>最大化</span></div> : null}
    return (
      <Wrapper
        fullScreen={this.topDialog}
        classPrefix={classPrefix}
        className={cx(className)}
        size={size}
        backdrop="static"
        onHide={this.handleSelfClose}
        keyboard={closeOnEsc && !store.loading}
        closeOnEsc={closeOnEsc}
        closeOnOutside={!store.dialogOpen && closeOnOutside}
        show={show}
        onEntered={this.handleEntered}
        onExited={this.handleExited}
        overlay={overlay}
        // style={{
        //   display: this.state.minWin ? 'none' : '',
        // }}
        container={
          containerId ?
            document.getElementById(containerId) ?
              () => document.getElementById(containerId) : env && env.getModalContainer ? env.getModalContainer : undefined
            :
            env && env.getModalContainer ? env.getModalContainer : undefined
        }
        enforceFocus={false}
        disabled={store.loading}
      >
        <Spinner overlay show={store.loading} />

        {this.topDialog ? null :
          <>{title && typeof title === 'string' ? (
            <div className={cx('Modal-header', headerClassName)}>
              {showCloseButton !== false && !store.loading ? (
                <a
                  data-tooltip={__('Dialog.close')}
                  data-position="left"
                  onClick={this.handleSelfClose}
                  className={cx('Modal-close')}
                >
                  <Icon icon="close" className="icon" />
                </a>
              ) : null}
              {/* <a
                  data-tooltip={__('Dialog.min')}
                  data-position="left"
                  onClick={this.handleSelfMin}
                  className={cx('Modal-close')}
                >
                  <Icon icon="compress-alt" className="compress-alt" />
                </a> */}
              <div className={cx('Modal-title')}>
                {filter(__(title), store.data, '| raw')}
              </div>
            </div>
          ) : title ? (
            <div className={cx('Modal-header', headerClassName)}>
              {showCloseButton !== false && !store.loading ? (
                <a
                  data-tooltip={__('Dialog.close')}
                  onClick={this.handleSelfClose}
                  className={cx('Modal-close')}
                >
                  <Icon icon="close" className="icon" />
                </a>
              ) : null}
              {render('title', title, {
                data: store.formData
              })}
            </div>
          ) : showCloseButton !== false && !store.loading ? (
            <a
              data-tooltip={__('Dialog.close')}
              onClick={this.handleSelfClose}
              className={cx('Modal-close')}
            >
              <Icon icon="close" className="icon" />
            </a>
          ) : null}</>}

        {header
          ? render('header', header, {
            data: store.formData
          })
          : null}

        {(!store.entered && lazyRender) || (lazySchema && !body) ? (
          <div className={cx('Modal-body', bodyClassName)}>
            <Spinner overlay show size="lg" />
          </div>
        ) : body ? (
          <div className={cx('Modal-body', bodyClassName)}>
            {this.renderBody(body, 'body')}
          </div>
        ) : null}

        {this.renderFooter()}

        {(body && store.drawerOpen)
          ? render(
            'drawer',
            {
              // 支持嵌套
              ...((store.action as Action) &&
                ((store.action as Action).drawer as object)),
              type: 'drawer'
            },
            {
              key: 'drawer',
              data: store.drawerData,
              onConfirm: this.handleDrawerConfirm,
              onClose: this.handleDrawerClose,
              show: store.drawerOpen,
              onAction: this.handleAction
            }
          )
          : null}

        {(body && store.dialogOpen)
          ? render(
            'dialog',
            {
              // 支持嵌套
              ...((store.action as Action) &&
                ((store.action as Action).dialog as object)),
              type: 'dialog'
            },
            {
              key: 'dialog',
              data: store.dialogData,
              onConfirm: this.handleDialogConfirm,
              onClose: this.handleDialogClose,
              show: store.dialogOpen,
              onAction: this.handleAction
            }
          )
          : null}
      </Wrapper>
    );
  }
}

@Renderer({
  type: 'dialog',
  storeType: ModalStore.name,
  storeExtendsData: false,
  isolateScope: true,
  shouldSyncSuperStore: (store: IServiceStore, props: any, prevProps: any) =>
    !!(
      (store.dialogOpen || props.show) &&
      (props.show !== prevProps.show ||
        isObjectShallowModified(prevProps.data, props.data))
    )
})
export class DialogRenderer extends Dialog {
  static contextType = ScopedContext;

  constructor(props: DialogProps, context: IScopedContext) {
    super(props);

    const scoped = context;
    scoped.registerComponent(this);
  }

  componentWillUnmount() {


    const scoped = this.context as IScopedContext;
    scoped.unRegisterComponent(this);
    super.componentWillUnmount();
  }

  tryChildrenToHandle(action: Action, ctx: object, rawAction?: Action) {
    const scoped = this.context as IScopedContext;

    if (action.fromDialog) {
      return false;
    }

    const targets: Array<any> = [];
    const { onConfirm, store } = this.props;

    if (action.target) {
      targets.push(
        ...action.target
          .split(',')
          .map(name => scoped.getComponentByName(name))
          .filter(item => item && item.doAction)
      );
    }

    if (!targets.length) {
      let components = scoped
        .getComponents()
        .filter(item => !~['drawer', 'dialog'].indexOf(item.props.type));

      const pool = components.concat();

      while (pool.length) {
        const item = pool.pop()!;

        if (~['crud', 'form', 'wizard'].indexOf(item.props.type)) {
          targets.push(item);
          break;
        } else if (~['drawer', 'dialog'].indexOf(item.props.type)) {
          continue;
        } else if (~['page', 'service'].indexOf(item.props.type)) {
          pool.unshift.apply(pool, item.context.getComponents());
        }
      }
    }

    if (targets.length) {
      store.markBusying(true);
      store.updateMessage();

      Promise.all(
        targets.map(target =>
          target.doAction(
            {
              ...action,
              from: this.$$id
            },
            ctx,
            true
          )
        )
      )
        .then(values => {
          if (
            (action.type === 'submit' ||
              action.actionType === 'submit' ||
              action.actionType === 'confirm') &&
            action.close !== false
          ) {
            onConfirm && onConfirm(values, rawAction || action, ctx, targets);
          } else if (action.close) {
            action.close === true
              ? action.actionType === 'form-print' ? undefined : this.handleSelfClose()
              : this.closeTarget(action.close);
          } else if ((action.type === 'submit' ||
            action.actionType === 'submit' ||
            action.actionType === 'confirm') &&
            action.close === false) {
            const serviceSchema = this.props.$schema.body;
            if (serviceSchema.type === 'service') {
              const targetComponent = serviceSchema.name && scoped.getComponentByName(serviceSchema.name)
              targetComponent?.reload?.()
            }
          }
          store.markBusying(false);
        })
        .catch(reason => {
          if (this.isDead) {
            return;
          }
          store.updateMessage(reason.message, true);
          store.markBusying(false);
        });

      return true;
    }

    return false;
  }

  handleAction(
    e: React.UIEvent<any>,
    action: Action,
    data: object,
    throwErrors: boolean = false,
    delegate?: IScopedContext
  ) {
    const { onAction, store, onConfirm, env } = this.props;

    if (action.from === this.$$id) {
      return onAction
        ? onAction(e, action, data, throwErrors, delegate || this.context)
        : false;
    }

    const scoped = this.context as IScopedContext;

    if (action.type === 'reset') {
      store.setCurrentAction(action);
      store.reset();
    } else if (
      action.actionType === 'close' ||
      action.actionType === 'cancel'
    ) {
      store.setCurrentAction(action);
      this.handleSelfClose();
      action.close && this.closeTarget(action.close);
    } else if (action.actionType === 'confirm') {
      store.setCurrentAction(action);
      this.tryChildrenToHandle(
        {
          ...action,
          actionType: 'submit'
        },
        data,
        action
      ) || this.handleSelfClose(undefined, true);
    } else if (action.actionType === 'next' || action.actionType === 'prev') {
      store.setCurrentAction(action);
      if (action.type === 'submit') {
        this.tryChildrenToHandle(
          {
            ...action,
            actionType: 'submit',
            close: true
          },
          data,
          action
        ) || this.handleSelfClose(undefined, true);
      } else {
        onConfirm([data], action, data, [], this.tableInstance);
      }
    } else if (action.actionType === 'dialog') {
      store.setCurrentAction(action);
      store.openDialog(data);
    } else if (action.actionType === 'drawer') {
      store.setCurrentAction(action);
      store.openDrawer(data);
    } else if (action.actionType === 'reload') {
      store.setCurrentAction(action);
      action.target && scoped.reload(action.target, data);
      if (action.close || action.type === 'submit') {
        this.handleSelfClose(undefined, action.type === 'submit');
        this.closeTarget(action.close);
      }
    } else if (this.tryChildrenToHandle(action, data)) {
      // do nothing
    } else if (action.actionType === 'ajax') {
      store.setCurrentAction(action);
      store
        .saveRemote(action.api as string, data, {
          successMessage: action.messages && action.messages.success,
          errorMessage: action.messages && action.messages.failed
        })
        .then(async () => {
          if (action.feedback && isVisible(action.feedback, store.data)) {
            await this.openFeedback(action.feedback, store.data);
          }

          const reidrect =
            action.redirect && filter(action.redirect, store.data);
          reidrect && env.jumpTo(reidrect, action);
          action.reload && this.reloadTarget(action.reload, store.data);
          if (action.close) {
            this.handleSelfClose();
            this.closeTarget(action.close);
          }
        })
        .catch(() => { });
    } else if (onAction) {
      let ret = onAction(
        e,
        {
          ...action,
          close: false
        },
        data,
        throwErrors,
        delegate || this.context
      );
      action.close &&
        (ret && ret.then
          ? ret.then(this.handleSelfClose)
          : setTimeout(this.handleSelfClose, 200));
    }
  }

  handleChildFinished(value: any, action: Action) {
    if ((action && action.from === this.$$id) || action.close === false) {
      return;
    }

    const scoped = this.context as IScopedContext;
    const components = scoped
      .getComponents()
      .filter((item: any) => !~['drawer', 'dialog'].indexOf(item.props.type));
    const onConfirm = this.props.onConfirm;
    const onClose = this.props.onClose;

    if (
      components.length === 1 &&
      (components[0].props.type === 'form' ||
        components[0].props.type === 'wizard') &&
      (action.close === true ||
        components[0].props.closeDialogOnSubmit !== false)
    ) {
      onConfirm && onConfirm([value], action, {}, components);
    } else if (action.close === true) {
      onClose();
    }
  }

  handleDialogConfirm(values: object[], action: Action, ...rest: Array<any>) {
    super.handleDialogConfirm(values, action, ...rest);
    const scoped = this.context as IScopedContext;
    const store = this.props.store;
    const dialogAction = store.action as Action;
    const reload = action.reload ?? dialogAction.reload;

    if (reload) {
      scoped.reload(reload, store.data);
    } else {
      // 没有设置，则自动让页面中 crud 刷新。
      scoped
        .getComponents()
        .filter((item: any) => item.props.type === 'crud')
        .forEach((item: any) => item.reload && item.reload());
    }
  }

  handleDrawerConfirm(values: object[], action: Action, ...rest: Array<any>) {
    super.handleDrawerConfirm(values, action);
    const scoped = this.context as IScopedContext;
    const store = this.props.store;
    const drawerAction = store.action as Action;

    // 稍等会，等动画结束。
    setTimeout(() => {
      if (drawerAction.reload) {
        scoped.reload(drawerAction.reload, store.data);
      } else if (action.reload) {
        scoped.reload(action.reload, store.data);
      } else {
        // 没有设置，则自动让页面中 crud 刷新。
        scoped
          .getComponents()
          .filter((item: any) => item.props.type === 'crud')
          .forEach((item: any) => item.reload && item.reload());
      }
    }, 300);
  }

  reloadTarget(target: string, data?: any) {
    const scoped = this.context as IScopedContext;
    scoped.reload(target, data);
  }

  closeTarget(target: string) {
    const scoped = this.context as IScopedContext;
    scoped.close(target);
  }
}
