/** CGReact导出类型定义*/
import React from "react";
/** 不能把下面这些类型作为全局type引入，必须import，否则会导致字段不提示*/
import {PageProp, PageState, ToastState} from "./cgreact-type-page";
import {CompProp, CompState} from "./cgreact-type-component";
import {LayoutConfig, LayoutProp, LayoutState} from "./cgreact-type-layout";
import {ModalProp, ModalState} from "./cgreact-type-modal";
import {ErrorCodeEnum} from "./cgreact-type-application";

export = CGReact; //使用这种方式书写，保障CGReact直接immport导出
export as namespace CGReact; //UMD的global导出，这样写即使不import CGReact也不会报错
declare namespace CGReact
{
    /** App全局上下文context应用类型定义*/
    abstract class CGReactApplication
    {
        constructor(currentWindow?: Window); // 构造函数,需要传入Main组件
        public WindowResizeSignal: CGReactSignal<UIEvent, "onWindowResize">; //窗口拖动信号
        public KeyboardPressSignal: CGReactSignal<KeyboardEvent, "onKeyDown">; //键盘按下信号
        public ApplicationIcon: string; //应用图标，可以配置base64或者路径
        public ApplicationTitle: string;//应用标题，可以配置字符串
        protected abstract renderApplicationPageView(): JSX;//初始化应用渲染的页面视图
        protected renderPageDefaultLoadingView(): JSX;//初始化页面类的加载中渲染
        protected renderComponentDefaultLoadingView(): JSX;//初始化组件类的加载中渲染
        protected renderPageDefaultErrorView(error: CGReactPageException): JSX;//@ts-ignore初始化错误页面的渲染
        protected async onApplicationInitialize(): Promise<void>; //应用初始化时回调
        protected onKeyDown(event: KeyboardEvent); //键盘按下回调，允许用户继承
        protected onWindowResize(event: UIEvent); //拖动窗口回调，允许用户继承
        public importAssetsScript(metaTag: string, url: string): Promise<HTMLScriptElement>;//引入第三方的JS文件，其中module为编译后的js路径，metaTag为script标签的标记
        public importAssetsSCSS(metaTag: string, content: string): HTMLStyleElement; //引入第三方的SCSS文件
        public importAssetsCSS(metaTag: string, url: string): HTMLLinkElement;//引入第三方CSS文件
        public getCGReactPageContext<T extends CGReactPage>(pageType: ClassOf<T>): T //获得任意继承CGReactPage页面的上下文实例，如果页面未渲染返回undefined
        public static lazyLoadPage(module: () => Promise<any>): React.ComponentType; //动态懒加载一个页面
        public static makeCGReactLogo(message: string): React.ReactElement; //静态方法创建Logo元素
        public static makeCGReactIconBase64(): string; //静态方法创建Logo的base64
        public static makeXBStarIconBase64(): string; //静态方法创建公司logo的base64
        [key: string]: any; //任意用户添加的方法
    }

    /** 核心页面抽象类CGReactPage类型定义*/
    abstract class CGReactPage<STATE extends PageState = PageState, PROP extends PageProp = PageProp> extends React.Component<PROP, STATE>
    {
        /** 原生参数定义*/
        public state: STATE; //继承一下state去除他的readonly属性
        public context: CGReactApplication; //Context的类型是Application
        public style: JSSKeyMap<StyleKey>; //页面样式的CSSModule类
        /*@ts-ignore CGReact拓展方法组*/
        protected async beforeInit(): Promise<void>//@ts-ignore初始化之前判定是否能够加载此页面
        protected abstract async initState(): Promise<STATE>;//初始化用户数据
        protected abstract renderView(): JSX;//初始化用户界面
        protected renderLoadingView(): JSX;//初始化预加载界面
        protected renderErrorView(error: CGReactPageException): JSX;//页面遇到错误展示的报错
        protected onPageStateReady(): void;//当state数据通过initState异步方法成功准备并返回的时候调用此方法
        protected onPageDidMount(): void;//当界面数据完成初始化时调用此方法，在页面加载时调用一次，重新渲染不会再次调用
        protected onPageDidUpdate(): void;//当界面重新渲染时调用此方法，每次render之后都会调用
        protected onPageWillUnMount(): void;//当Page从页面卸载时时回调这个函数
        public refresh(): void;//无条件刷新页面
        public reload(): void;//重新加载页面数据
        public toast(message: string | ToastState, level?: "info" | "warn" | "error" | "success", last?: number): void;//展示一个吐司
        public dialog(message: ModalState | string); //展示一个对话框
        public loading(last?: number | true, type?: "dot" | "circle"); //展示一个加载框
        public dismiss(): void; //取消显示loading对话框
        public redirectToURL(url: string, params?: { [key: string]: string }): void;//页面重定向到指定的地址
        public getParamFromURL(key: string): string;//从当前地址路径中提取信息
    }

    /** 核心页面抽象类CGReactPage类型定义*/
    abstract class CGReactComponent<STATE extends CompState = CompState, PROP extends CompProp = CompProp> extends React.Component<PROP, STATE>
    {
        public state: STATE; //继承一下state去除他的readonly属性
        public parent: CGReactPage;//父页面的引用，通过parent获得父控件的引用
        public modal: CGReactModal; //页面集成的modal类引用
        public style: JSSKeyMap<StyleKey>; //页面样式的CSSModule类
        public layout: CGReactLayout; //@ts-ignore  元素嵌套的父布局框架
        protected async initState(init: STATE): Promise<STATE>;//初始化组件数据,在constructor之后组件渲染时，onComponentStateReady,renderView和onComponentDidMount之前调用
        protected abstract renderView(): JSX;//初始化用户界面
        protected onComponentStateReady(): void;//当state数据通过initState异步方法成功准备并返回的时候调用此方法
        protected onComponentDidMount(): void;//当界面数据完成初始化时调用此方法，在页面加载时调用一次，重新渲染不会再次调用
        protected onComponentDidUpdate(): void;//当界面重新渲染时调用此方法，每次render之后都会调用
        protected onComponentUnmount(): void;//组件卸载或者对话框关闭不显示时回调此函数
        protected onModalComponentCancel(): void;//点击模态框取消按钮时回调此次函数
        protected onModalComponentConfirm(): void;//点击模态框确认按钮时回调此次函数
        public refresh(sync?: boolean): void; //无条件刷新页面
        public reload(state?: FreeNecessary<STATE>): void;// 重新加载当前组件，会清除state重新调用initState赋值
        public display(state?: FreeNecessary<STATE> | false): void;//此方法针对ModalComponent生效，展示模态对话框框
        public dismiss(): void; // 此方法针对ModalComponent生效,模态对话框消失
    }

    /** CGReact布局框架类*/
    class CGReactLayout<STATE extends LayoutState = LayoutState, PROP extends LayoutProp = LayoutProp> extends React.Component<PROP, STATE>
    {
        /* CGReact拓展方法组*/
        public LayoutConfig: LayoutConfig; //布局计算后生成的配置
        public LayoutFormState: { theme: "default" | "pane", fluid: boolean; }; //表单配置
        public CurrentLayoutDivRef: React.RefObject<HTMLDivElement>; //布局元素的dom引用
        public display();// 作为对话框显示
        public dismiss(); //取消对话框显示
    }

    /** CGReact模态框*/
    class CGReactModal extends React.Component<ModalProp, ModalState>
    {
        /* CGReact拓展方法组*/
        public display();// 作为对话框显示
        public dismiss(); //取消对话框显示
        protected onModalCancelClick(): void; //对话框关闭回调
        protected onModalConfirmClick(): void;//对话框确认回调
    }

    /*CGReact信号类定义*/
    class CGReactSignal<MESSAGE, CALLBACK extends string>
    {
        constructor(key: CALLBACK); //构造函数需要插槽方法名称
        public bind(slot: CGReactSlot<MESSAGE, CALLBACK>, binder?: object); //绑定一个插槽到信号上
        public unbind(slot: CGReactSlot<MESSAGE, CALLBACK>); //解除插槽的绑定
        public emit(data: MESSAGE); //触发信号，所有的插槽都将接收到消息
    }

    /** 暴露框架异常类*/
    class CGReactPageException extends Error
    {
        constructor(code: ErrorCodeEnum, explain?: string, message?: string); //抛出异常的构造函数
        public errorCode: ErrorCodeEnum; //错误代码
        public errorExplain: string; //错误描述
        public errorMessage: string; //错误处理方案
        public getErrorCode(): number;//获取错误码
        public getErrorExplain(): string;//获取错误描述
        public getErrorMessage(): string;//获取错误处理信息
        public static throw(code: ErrorCodeEnum, explain?: string, message?: string);//调用静态函数抛出异常
    }

    /** 暴露框架注解*/
    function affectStyle(style: string | JSS, tag?: string); // 方法注解，用户function等函数
    /*CGReact常用工具函数*/
    namespace CGReactUtils
    {
        function generateUUID(): string;//生成随机的UUID
        function isCGReactComponent(element: any): boolean;//判断JSX元素是否为CGReact组件
        function copyObject<M>(object: M): M;//递归拷贝对象的所有属性
        function resetObject<T extends object>(from: FreeNecessary<T>, to: T);//合并两个元素，undefine也会重置
        function mergeObject<T extends object>(from: FreeNecessary<T>, to: T, defaultValue?: T): T;//合并两个object
    }
    /** 导出信号和插槽的定义*/
    type CGReactSlot<DATATYPE, CALL extends string> = { [key in CALL]: (data: DATATYPE) => void };
    type WindowResizeSlot = { onWindowResize(message: UIEvent): void; } //窗口Resize事件的插槽
    type KeyboardPressSlot = { onKeyDown(message: KeyboardEvent): void; } //键盘事件的插槽
}
