import {
  AnyFunction, IsNever, Param1Type, RequiredKeys,
} from '@22g/utility-types';

import { NIMError } from './Error';

export * from './Error';


/**
 * 地理位置对象
 * - [相关文档](https://dev.yunxin.163.com/docs/interface/即时通讯Web端/NIMSDK-Web/Geo.html)
 */
export interface NIMGeo {
  /** 经度 */
  lng: number;
  /** 纬度 */
  lat: number;
  /** 地址描述 */
  title: string;
}

/** 文件类型，主要用在 [[NIM.previewFile|`NIM.previewFile`]] */
export const enum NIMFileType {
  /** 图片 */
  image = 'image',
  /** 音频 */
  audio = 'audio',
  /** `视频` */
  video = 'video',
  /** `文件` */
  file = 'file',
}

/**
 * 文件对象
 * - [相关文档](https://dev.yunxin.163.com/docs/interface/即时通讯Web端/NIMSDK-Web/File.html)
 */
export interface NIMFile {
  url: string;
  /** 文件名(带后缀) */
  name: string;
  /** 文件大小(btye) */
  size: number;
  /** 文件内容的MD5 */
  md5: string;
  /** 文件后缀 */
  ext: string;
}



/** 图片文件 */
export interface NIMImageFile extends NIMFile {
  /** 宽(px) */
  w: number;
  /** 高(px) */
  h: number;
}


/** 视频文件 */
export interface NIMVideoFile extends NIMFile {
  /** 视频长度(ms) */
  dur: number;
  /** 分辨率宽(px) */
  w: number;
  /** 分辨率高(px) */
  h: number;
}

/** 音频文件 */
export interface NIMAudioFile extends NIMFile {
  /** 音频长度(ms) */
  dur: number;
  /** 实时转成 mp3 流的 url, 此 url 支持的格式有: mp3, wav, aac, wma, wmv, amr, mp2, flac, vorbis, ac3 */
  mp3Url: string;
}


/**
 * @typeparam $Opts 参数(不带done)
 * @typeparam $Res 成功时返回
 * @typeparam $ErrRes 错误时返回
 * @typeparam $Err 错误信息
 */
export type NIMAsyncFuncOptions<$Opts extends {} = {}, $Res = unknown, $ErrRes = unknown, $Err extends NIMError = NIMError> = $Opts & {
  /** 回调函数 */
  done?(...[err, res]: NIMFuncDoneResult<$Res, $ErrRes, $Err>): void;
};

/**
 * 返回操作成功时的响应的对象类型
 * @typeparam $Opts 参数(带done)
 * - 例子:
 * ```ts
 * type _ = NIMAsyncFuncOptionsSuccessRes<NIMAsyncFuncOptions<$Opts, $Res, $ErrRes, $Err>> // 返回 $Res
 * ```
 */
export type NIMAsyncFuncOptionsSuccessRes<$Opts extends NIMAsyncFuncOptions<{}>> = $Opts extends NIMAsyncFuncOptions<infer _A, infer _B, infer _C, infer _D> ? _B : never;

/**
 * @typeparam $Opts 参数(带done)
 * @typeparam $R 函数返回(一般为`void`)
 */
export interface NIMAsyncFunc<$Opts extends NIMAsyncFuncOptions<{}>, $R = void> {
  (...args: Parameters<IsNever<RequiredKeys<$Opts>, (options?: $Opts) => void, (options: $Opts) => void>>): $R;
}



/**
 * @typeparam Res 成功时返回
 * @typeparam ErrRes 错误时返回
 * @typeparam Err 错误信息
 */
export type NIMFuncDoneResult<Res = unknown, ErrRes = unknown, Err extends NIMError = NIMError> = Parameters<(err: Err, res: ErrRes) => void> | Parameters<(err: null, res: Res) => void>;
/**
 * @typeparam Res 成功时返回
 * @typeparam ErrRes 错误时返回
 * @typeparam Err 错误信息
 */
export type NIMFuncPromiseResult<Res = unknown, ErrRes = unknown, Err extends NIMError = NIMError> = { err: null, res: Res } | { err: Err, res: ErrRes };

export type NIMAsyncFuncPromiseify<T extends AnyFunction> =
  NonNullable<Param1Type<T>> extends NIMAsyncFuncOptions<infer _A, infer _B, infer _C, infer _D>
  ? (...args: Parameters<T>) => Promise<NIMFuncPromiseResult<_B, _C, _D>>
  : never;

/**
 * 处理图片类型 [[NIM.processImage|`处理图片`]] 用到
 */
export const enum NIMProcessImageType {
  /** [[NIM.qualityImage|`修改图片质量`]] */
  quality = 'quality',
  /** [[NIM.interlaceImage|`interlace 图片`]] */
  interlace = 'interlace',
  /** [[NIM.rotateImage|`旋转图片`]] */
  rotate = 'rotate',
  /** [[NIM.blurImage|`高斯模糊图片`]] */
  blur = 'blur',
  /** [[NIM.cropImage|`裁剪图片`]] */
  crop = 'crop',
  /** [[NIM.thumbnailImage|`生成缩略图`]] */
  thumbnail = 'thumbnail',
}
