type Container = any;
type Middleware = any;
type Pipeline = any;

export interface Exception {
  constructor: (name: string, message: string) => void;
}

type Model = any;
type Service = any;
type ServiceProvider = any;

declare type TContentType = "REQUEST_PAYLOAD" | "FORM_DATA";
declare type IHttpSendConfig = {
  host?: string;
  headers?: Record<string, any>;
  mode?: TContentType;
  responseData?: boolean;
};

declare type TResponseDataReturn = {
  statusCode: number;
  msg: string;
  data: any;
  timestamp: number;
};

interface IResponseReturn extends Response {
  data: TResponseDataReturn;
}

interface IHelper {
  env(): Record<any, any>;

  storage(name: string): Record<any, any>;

  storage(name: string, payload?: any): void;

  cookies(name: string): Record<any, any>;

  cookies(name: string, payload?: any): void;

  session(name: string): Record<any, any>;

  session(name: string, payload?: any): void;

  /**
   * 发送一个http请求
   * @param api 接口key
   * @param data  请求数据
   * @param handle 处理Response的函数
   */
  http(
    api: string,
    data?: Record<string, any>,
    handle?: (response: IResponseReturn) => void
  ): Promise<TResponseDataReturn>;

  send(
    api: string,
    data?: Record<string, any>,
    handle?: (response: IResponseReturn) => void,
    config?: IHttpSendConfig
  ): Promise<IResponseReturn>;
}

export declare abstract class Command {
  protected payload: any;
  protected $helper: IHelper;

  constructor(...payload: any[]);

  abstract handle(...args: any[]): any | Promise<any> | void;
}

declare type Callback = (
  item: Record<any, any>,
  index?: number
) => Record<any, any>;

export declare abstract class Transformer {
  private readonly data;
  private payload;

  /**
   * Method constructor
   * @param {*} data 需处理的数据
   * @param {*} payload 携带的载荷
   * @returns
   */
  protected constructor(data: any, payload?: unknown);

  /**
   * Method transform
   * 转换方法
   * @param {Object|String|Number} data
   * @param tData
   * @returns
   */
  transform(data: any, tData?: any): any;

  /**
   * Method create
   * 创建新数据
   * @return {Array/Object|String|Number|*}
   */
  create(callback: Callback): any;

  /**
   * 格式化数字
   * @param {String|Number} number 待处理数字
   * @param {Number} places 小数点位数 -1为原样保留
   * @param {String} thousand 千位字符串 默认为空
   * @param {String} decimal 小数点替换字符 默认为.
   * @return {String|Number}
   */
  formatNumber(
    number: string | number,
    places?: number | string,
    thousand?: string,
    decimal?: string
  ): string;

  /**
   * formatDate 日期格式化
   * @param {string|number} timestamp
   * @returns
   */
  formatDate(
    timestamp?: number | string | unknown
  ): Record<string, number | string>;
}

export declare abstract class Vue2Adapter {
  component(name: string, component: any): void;

  use(plug: any): void;

  setConfig(configs: Record<string, any>): void;

  run(root: string): void;
}

export declare abstract class VuexAdapter {
  getStore(): Record<string, any>;
}

export declare abstract class AxiosAdapter {
  request(): Promise<any>;
}

type Lib = any;

declare function isArray(obj: any): obj is any[];

declare function isNull(obj: any): obj is null;

declare function isBoolean(obj: unknown): obj is boolean;

declare function isObject(obj: any): obj is Record<string, unknown>;

declare const isPromise: <T>(obj: unknown) => obj is Promise<T>;

declare function isString(obj: any): obj is string;

declare function isNumber(obj: any): obj is number;

declare function isRegExp(obj: any): boolean;

declare function isDate(obj: any): boolean;

declare function isColor(color: any): boolean;

declare function isUndefined(obj: any): obj is undefined;

declare function isFunction(obj: any): obj is (...args: any[]) => any;

declare function isEmptyObject(obj: any): boolean;

declare function isEmpty(obj: any): boolean;

declare function isExist(obj: any): boolean;

declare function isWindow(el: any): el is Window;

declare function isPhone(obj: any): boolean;

declare function isEmail(obj: any): boolean;

declare const is_isArray: typeof isArray;
declare const is_isNull: typeof isNull;
declare const is_isBoolean: typeof isBoolean;
declare const is_isObject: typeof isObject;
declare const is_isPromise: typeof isPromise;
declare const is_isString: typeof isString;
declare const is_isNumber: typeof isNumber;
declare const is_isRegExp: typeof isRegExp;
declare const is_isDate: typeof isDate;
declare const is_isColor: typeof isColor;
declare const is_isUndefined: typeof isUndefined;
declare const is_isFunction: typeof isFunction;
declare const is_isEmptyObject: typeof isEmptyObject;
declare const is_isEmpty: typeof isEmpty;
declare const is_isExist: typeof isExist;
declare const is_isWindow: typeof isWindow;
declare const is_isPhone: typeof isPhone;
declare const is_isEmail: typeof isEmail;
declare namespace is {
  export {
    is_isArray as isArray,
    is_isNull as isNull,
    is_isBoolean as isBoolean,
    is_isObject as isObject,
    is_isPromise as isPromise,
    is_isString as isString,
    is_isNumber as isNumber,
    is_isRegExp as isRegExp,
    is_isDate as isDate,
    is_isColor as isColor,
    is_isUndefined as isUndefined,
    is_isFunction as isFunction,
    is_isEmptyObject as isEmptyObject,
    is_isEmpty as isEmpty,
    is_isExist as isExist,
    is_isWindow as isWindow,
    is_isPhone as isPhone,
    is_isEmail as isEmail,
  };
}

// interface Core {
// 	Container: Container
// 	Middleware: Middleware
// 	Pipeline: Pipeline
// 	Exception: Exception
// 	Model: Model
// 	Service: Service
// 	ServiceProvider: ServiceProvider
// 	Command: Command
// 	Transformer: Transformer
// 	Lib: Lib
// 	Vue2Adapter: any
// 	VuexAdapter: any
// 	AxiosAdapter: any
// 	UniappRequestAdapter: any
//
// }

type WebSocketEventCallback = (event: any) => any;

type Heartbeat = (WebSocketClient: any) => void;

export declare interface WebSocketClient {
  init({ ws, wss, insName, heartRate, restart }, heartbeat): void;

  destroy(insName?: string): void;

  getWsState(
    insName?: string
  ): "CONNECTING" | "OPEN" | "CLOSING" | "CLOSED" | "FAIL";

  wsErrorEventListener(
    callback: WebSocketEventCallback,
    insName?: string
  ): void;

  wsCloseEventListener(
    callback: WebSocketEventCallback,
    insName?: string
  ): void;

  wsOpenEventListener(callback: WebSocketEventCallback, insName?: string): void;

  sendMessage(msg: string, insName?: string, isCloseWarn?: boolean);

  receiveMessage(callback: WebSocketEventCallback, insName?: string);

  heartbeat(callback: Heartbeat, insName?: string);
}

interface Core {
  getInstance(): this;

  bindAdapter(acapter: any, func: any): void;

  getAdapter(adapter: any): any;

  setAppConfig(config: Record<string, any>): void;

  version: string;

  run(callback: (services: Record<string, any>) => void): void;
}

declare const framework4js: Core;

export default framework4js;
