/* Menu */
declare namespace Menu {
  interface MenuOptions {
    path: string;
    name: string;
    component?: string | (() => Promise<unknown>);
    redirect?: string;
    meta: MetaProps;
    children?: MenuOptions[];
  }
  interface MetaProps {
    /**
     * @description 菜单图标
     */
    icon?: string;
    title: string;
    activeMenu?: string;
    isLink?: string;
    /**
     * @description 是否隐藏菜单
     */
    isHide: boolean;
    isFull: boolean;
    isAffix: boolean;
    isKeepAlive: boolean;
    /**
     * @description 菜单是否为二级特殊菜单，其子集不展示在主菜单
     */
    isSubMenu?: boolean;
    /**
     * @description 是否主动禁用菜单
     */
    isDisabled?: boolean;
    /**
     * @description 菜单权限值
     */
    funid?: number;
    /**
     * @description 是否以el-menu-item-group的形式渲染
     */
    isGroup?: boolean;
  }
}

/* FileType */
declare namespace File {
  type ImageMimeType =
    | "image/apng"
    | "image/bmp"
    | "image/gif"
    | "image/jpeg"
    | "image/pjpeg"
    | "image/png"
    | "image/svg+xml"
    | "image/tiff"
    | "image/webp"
    | "image/x-icon";

  type ExcelMimeType = "application/vnd.ms-excel" | "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
}

/* Vite */
declare type Recordable<T = any> = Record<string, T>;

declare interface ViteEnv {
  VITE_USER_NODE_ENV: "development" | "production" | "test";
  VITE_GLOB_APP_TITLE: string;
  VITE_GLOB_APP_COMPANY: string;
  VITE_PORT: number;
  VITE_OPEN: boolean;
  VITE_REPORT: boolean;
  VITE_BUILD_COMPRESS: "gzip" | "brotli" | "gzip,brotli" | "none";
  VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE: boolean;
  VITE_DROP_CONSOLE: boolean;
  VITE_PWA: boolean;
  VITE_PUBLIC_PATH: string;
  VITE_API_URL: string;
  VITE_PROXY: [string, string][];
}

interface ImportMetaEnv extends ViteEnv {
  __: unknown;
}

/* __APP_INFO__ */
declare const __APP_INFO__: {
  pkg: {
    name: string;
    version: string;
    dependencies: Recordable<string>;
    devDependencies: Recordable<string>;
  };
  lastBuildTime: string;
};

export type TimeoutHandle = ReturnType<typeof global.setTimeout>;
declare type IntervalHandle = ReturnType<typeof setInterval>;

declare type Nullable<T> = T | null;

declare global {
  interface Window {
    existLoading: boolean;
    lazy: number;
    unique: number;
    tokenRefreshing: boolean;
    requests: Function[];
    eventSource: EventSource;
    loadLangHandle: Record<string, any>;
  }
}

/* Generic Tools */
type ObjToKeyValUnion<T> = {
  [K in keyof T]: { key: K; value: T[K] };
}[keyof T];

type ObjToKeyValArray<T> = {
  [K in keyof T]: [K, T[K]];
}[keyof T];
