/**
 * @file 组件 Env，包括如何发送 ajax，如何通知，如何跳转等等。。
 */
import React from 'react';
import {RendererConfig} from './factory';
import {ThemeInstance} from './theme';
import {Action, Api, Payload, Schema} from './types';
import {IScopedContext} from './Scoped';
import {
  RendererEvent,
  RendererEventListener,
  EventListeners
} from './utils/renderer-event';

export interface RendererEnv {
  fetcher: (api: Api, data?: any, options?: object) => Promise<Payload>;
  isCancel: (val: any) => boolean;
  notify: (// 控制toast弹框
    type: 'error' | 'success' | 'warning' | 'info',
    msg: string,
    conf?: {
      closeButton?: boolean;
      timeout?: number;
    }
  ) => void;
  jumpTo: (to: string, action?: Action, ctx?: object) => void;// 跳转
  alert: (msg: string) => void;
  confirm: (msg: string, title?: string) => Promise<boolean>;
  updateLocation: (location: any, replace?: boolean) => void;// 跳转路由 同jumpTo

  /**
   * 阻止路由跳转，有时候 form 没有保存，但是路由跳转了，导致页面没有更新，
   * 所以先让用户确认一下。
   *
   * 单页模式需要这个，如果非单页模式，不需要处理这个。
   */
  blockRouting?: (fn: (targetLocation: any) => void | string) => () => void;
  isCurrentUrl: (link: string, ctx?: any) => boolean | {params?: object};// 用来判断是否目标地址当前地址。如果有search返回query对象 其他的返回boolean

  /**
   * 监控路由变化，如果 jssdk 需要做单页跳转需要实现这个。
   */
  watchRouteChange?: (fn: () => void) => () => void;
  rendererResolver?: (// 根据path 或schema.type匹配 内存里面注册的所有渲染器 返回匹配上的渲染器
    path: string,
    schema: Schema,
    props: any
  ) => null | RendererConfig;
  copy?: (contents: string) => void;
  getModalContainer?: () => HTMLElement;// 弹框的容器
  theme: ThemeInstance;
  affixOffsetTop: number;
  affixOffsetBottom: number;
  loadRenderer: (// 渲染器加载报错占位提示dom
    schema: Schema,
    path: string,
    reRender: Function
  ) => Promise<React.ReactType> | React.ReactType | JSX.Element | void;
  loadChartExtends?: () => void | Promise<void>;
  bindEvent: (context: any) => (() => void) | undefined;
  dispatchEvent: (
    e:
      | string
      | React.ClipboardEvent<any>
      | React.DragEvent<any>
      | React.ChangeEvent<any>
      | React.KeyboardEvent<any>
      | React.TouchEvent<any>
      | React.WheelEvent<any>
      | React.AnimationEvent<any>
      | React.TransitionEvent<any>
      | React.MouseEvent<any>,
    context: any,
    scoped: IScopedContext,
    data: any,
    broadcast?: RendererEvent<any>
  ) => Promise<RendererEvent<any> | undefined>;
  rendererEventListeners: RendererEventListener[];

  /**
   * 过滤 html 标签，可用来添加 xss 保护逻辑
   */
  filterHtml: (input: string) => string;
  [propName: string]: any;
}

export const EnvContext = React.createContext<RendererEnv | void>(undefined);