import { LiteralUnion, NullOr, PickIncludeVal, PickKeysIncludeVal } from '@22g/utility-types';
import { NIMClientType, NIMLoginPort } from './LoginPort';
import { NIMUser } from './User';
import { NIMTeam } from './Team';
import { NIMTeamMember } from './TeamMember';
import { NIMServerSession, NIMSession } from './Session';
import { NIMMessage, NIMTipMessage } from './Message';
import { NIMSystemMessage } from './SystemMessage';
import { NIMError, NIMErrorCode } from './Basic';
import { NIMFriend } from './Friend';
import { NIMMarkInfo, NIMRelation } from './Relation';
import { NIMSuperTeam } from './SuperTeam';
import { NIMSuperTeamMember } from './SuperTeamMember';
import { NIMMsgEvent } from './MsgEvent';
import { NIMComment } from './Comment';


/** 初始化时传入的配置 */
export interface NIMInitConf {
  /**
   * 是否开启调试, 如果开启调试, 将会在控制台输出一些log。默认 `false` 不输出日志, 可以传 `true` 来开启日志。
   * @default false
   */
  debug?: boolean | object;
  /**
   * 是否对日志做额外的处理，诸如日志存储、日志上报等等，该函数会截获console日志的参数，供开发者使用
   * @default null
   */
  logFunc?: null | Function | object;
  /**
   * secure 模式下会通过 https 协议跟服务器建立连接, 非 secure 模式下会通过 http 协议跟服务器建立连接
   * @default true
   */
  secure?: boolean;
  /** 在云信管理后台查看应用的 appKey */
  appKey: string;
  /** 帐号, 应用内唯一 */
  account: NIMUser['account'];
  /** 帐号的 token, 用于建立连接 */
  token: string;
  /**
   * nos文件存储全局配置，存储场景，实例有效
   * @default 'im'
   */
  nosScenes?: string;
  /**
   * nos文件存储全局配置，存储有效时间，实例有效，默认Infinity 不得小于一天，单位秒
   * @default Infinity
   */
  nosSurvivalTime?: number;
  /**
   * 连接建立后的回调 , 会传入一个对象, 包含登录的信息, 有以下字段
   * - `lastLoginDeviceId`: 上次登录的设备的设备号
   * -  `customTag`: 客户端自定义tag,登录时多端同步改字段，最大32个字符
   * -  `connectionId`: 本次登录的连接号
   * -  `ip`: 客户端IP
   * -  `port`: 客户端端口
   * -  `country`: 本次登录的国家
   */
  onconnect?(result: NIMOnconnectRes): void;
  /**
   * 即将重连的回调
   * -  此时说明 SDK 已经断开连接, 请开发者在界面上提示用户连接已断开, 而且正在重新建立连接
   * -  此回调会收到一个对象, 包含额外的信息, 有以下字段
   *  -  `duration`: 距离下次重连的时间
   *  -  `retryCount`: 重连尝试的次数
   */
  onwillreconnect?(result: NIMOnwillreconnectRes): void;
  /**
   * 断开连接后的回调
   * - 此时说明 SDK 处于断开状态, 开发者此时应该根据错误码提示相应的错误信息, 并且跳转到登录页面
   * - 此回调会收到一个对象, 包含错误的信息, 有以下字段
   *    + `code`: 出错时的错误码, 可能为空
   *      - `302`: 账号或者密码错误, 请跳转到登录页面并提示错误
   *      - `417`: 重复登录, 已经在其它端登录了, 请跳转到登录页面并提示错误
   *      - `'kicked'`: 被踢
   * - 当 `code` 为 `'kicked'` 的时候, 此对象会有以下字段
   *   + `reason`: 被踢的原因
   *      - `samePlatformKick`: 不允许同一个帐号在多个地方同时登录
   *      - `serverKick`: 被服务器踢了
   *      - `otherPlatformKick`: 被其它端踢了
   *   + `message`: 文字描述的被踢的原因
   */
  ondisconnect?(result: NIMOndisconnectRes): void;
  /**
   * 发生错误的回调, 会传入 [[NIMError|`错误`]] 对象
   */
  onerror?(error: NIMOnerrorResRes, obj: unknown): void;
  /**
   * 多端登录状态变化的回调, 会收到 [[NIMLoginPort|`登录端`]] 列表, 以下情况会收到此回调
   * - 登录时其它端在线
   * - 登录后其它端上线或者下线
   */
  onloginportschange?(loginPorts: NIMOnloginportschangeRes): void;
  /**
   * 是否同步黑名单和静音列表
   * - `false` 就收不到黑名单和静音列表, 即不会收到`onblacklist`回调和`onmutelist`回调, 开发者后续可以调用[[NIM.getRelations|`获取黑名单和静音列表`]]来获取黑名单和静音列表。
   * @default true
   */
  syncRelations?: boolean;
  /**
   * 同步黑名单的回调, 会传入黑名单列表`blacklist`
   * - `blacklist` 的属性 `invalid` 包含被删除的黑名单列表
   * - 此回调是增量回调, 可以调用 [[NIM.mergeRelations|`NIM.mergeRelations`]] 和 [[NIM.cutRelations|`NIM.cutRelations`]] 来合并数据
   */
  onblacklist?(blackList: NIMOnblacklistRes): void;
  /**
   * 当前登录用户在其它端[[NIM.markInBlacklist|`加入黑名单/从黑名单移除`]]后的回调, 会传入一个参数, 包含两个字段
   * - `account`: 要加入黑名单/从黑名单移除的账号
   * - `isAdd`: `true`表示加入黑名单, `false`表示从黑名单移除
   */
  onsyncmarkinblacklist?(markInfo: NIMOnsyncmarkinblacklistRes): void;
  /**
   * 同步静音列表的回调, 会传入静音列表`mutelist`
   * - `mutelist` 的属性 [[NIMOnmutelistRes|`invalid`]] 包含被删除的静音列表
   * - 此回调是增量回调, 可以调用 [[NIM.mergeRelations|`NIM.mergeRelations`]] 和 [[NIM.cutRelations|`NIM.cutRelations`]] 来合并数据
   */
  onmutelist?(muteList: NIMOnmutelistRes): void;
  /**
   * 当前登录用户在其它端[[NIM.markInMutelist|`加入静音列表/从静音列表移除`]]后的回调, 会传入一个参数, 包含两个字段
   * -  `account`: 要加入黑名单/从黑名单移除的账号
   * -  `isAdd`: `true`表示加入静音列表, `false`表示从静音列表移除
   */
  onsyncmarkinmutelist?(markInfo: NIMOnsyncmarkinmutelistRes): void;
  /**
   * 是否同步好友列表, 默认true.
   * - `false`就收不到 [[NIMInitConf.onfriends|`onfriends`]] 回调, 开发者后续可以调用[[NIM.getFriends|`获取好友列表`]]来获取好友列表。
   * @default true
   */
  syncFriends?: boolean;
  /**
   * 同步好友列表的回调
   * - 同步好友列表的回调, 会传入好友列表。没有好友时，使用数据库会调用回调传空数组，否则不回调。
   */
  onfriends?(friends: NIMOnfriendsRes): void;
  /**
   * 当前登录用户在其它端进行好友相关的操作后的回调
   * - 操作包括
   *    + [直接加为好友](https://dev.yunxin.163.com/docs/interface/即时通讯Web端/NIMSDK-Web/NIM.html#addFriend) [[NIM.addFriend|`NIM.addFriend`]]
   *    + [申请加为好友](https://dev.yunxin.163.com/docs/interface/即时通讯Web端/NIMSDK-Web/NIM.html#applyFriend) [[NIM.applyFriend|`NIM.applyFriend`]]
   *    + [通过好友申请](https://dev.yunxin.163.com/docs/interface/即时通讯Web端/NIMSDK-Web/NIM.html#passFriendApply) [[NIM.passFriendApply|`NIM.passFriendApply`]]
   *    + [拒绝好友申请](https://dev.yunxin.163.com/docs/interface/即时通讯Web端/NIMSDK-Web/NIM.html#rejectFriendApply) [[NIM.rejectFriendApply|`NIM.rejectFriendApply`]]
   *    + [删除好友](https://dev.yunxin.163.com/docs/interface/即时通讯Web端/NIMSDK-Web/NIM.html#deleteFriend) [[NIM.deleteFriend|`NIM.deleteFriend`]]
   *    + [更新好友](https://dev.yunxin.163.com/docs/interface/即时通讯Web端/NIMSDK-Web/NIM.html#updateFriend) [[NIM.updateFriend|`NIM.updateFriend`]]
   * - 此回调会收到一个参数`obj`, 它有一个字段`type`的值为操作的类型, 具体类型如下：
   *    + `'addFriend'` (直接加为好友), 此时`obj`的字段如下:
   *      - `account` 的值为被直接加为好友的账号
   *      - `friend` 为被直接加为好友的[[NIMFriend|`好友对象`]]
   *      - `ps` 为附言
   *    + `'applyFriend'` (申请加为好友), 此时`obj`的字段如下:
   *      - `account` 的值为被申请加为好友的账号
   *      - `ps` 为附言
   *    + `'passFriendApply'` (通过好友申请), 此时obj的字段如下:
   *      - `account` 的值为被通过好友申请的账号
   *      - `friend` 为被通过好友申请的[[NIMFriend|`好友对象`]]
   *      - `ps` 为附言
   *    + `'rejectFriendApply'` (拒绝好友申请), 此时`obj`的字段如下:
   *      - `account` 的值为被拒绝好友申请的账号
   *      - `ps` 为附言
   *    + `'deleteFriend' ` (删除好友), 此时`obj`的字段如下:
   *      - `account` 的值为被删除好友的账号
   *    + `'updateFriend' ` (更新好友), 此时`obj`的字段如下:
   *      - `friend` 的值为被更新的[[NIMFriend|`好友对象`]]
   *
   */
  onsyncfriendaction?(result: NIMOnsyncfriendactionRes): void;
  /**
   * 同步登录用户名片的回调,会传入[[NIMUser|`用户名片`]]
   */
  onmyinfo?(userCard: NIMOnmyinfoRes): void;
  /** 当前登录用户在其它端修改自己的个人名片之后的回调, 会传入[[NIMUser|`用户名片`]] */
  onupdatemyinfo?(userCard: NIMOnupdatemyinfoRes): void;
  /**
   * 是否同步好友对应的 [[NIMUser|`用户名片`]] 列表
   * - `false` 就收不到`onusers`回调.
   * @default true
   */
  syncFriendUsers?: boolean;
  /**
   * 同步好友用户名片的回调, 会传入 [[NIMUser|`用户名片`]] 数组`
   */
  onusers?(userCards: NIMOnusersRes): void;
  /**
   * 用户名片更新后的回调, 会传入 [[NIMUser|`用户名片`]]
   */
  onupdateuser?(userCard: NIMOnupdateuserRes): void;
  /**
   * 是否同步超大群列表
   * - `false` 就收不到群列表, 即不会收到 [[NIMInitConf.onSuperTeams|`NIMInitConf.onSuperTeams`]] 回调, 开发者后续可以调用 [[NIM.getSuperTeams|`获取超大群列表`]] 来获取群列表.
   * @default true
   */
  syncSuperTeams?: boolean;
  /**
   * 同步超大群列表的回调, 会传入[[NIMSuperTeam|`超大群`]]数组
   */
  onSuperTeams?(teams: NIMOnSuperTeamsRes): void;
  /**
   * 当前登录者创建超大群后的回调, 会传入[[NIMSuperTeam|`超大群`]]
   */
  onSyncCreateSuperTeam?(team: NIMOnSyncCreateSuperTeamRes): void;
  /** 更新超大群的回调, 此方法接收一个参数, 更新后的群信息 */
  onUpdateSuperTeam?(team: NIMOnUpdateSuperTeamRes): void;
  /**
   * 群成员信息更新后的回调
   * - 会传入[[NIMSuperTeamMember|`超大群群成员`]]对象，不过此时的信息是不完整的, 只会包括被更新的字段。当前登录帐号在其它端修改自己在群里面的昵称时也会收到此回调
   */
  onUpdateSuperTeamMember?(member: NIMOnUpdateSuperTeamMemberRes): void;
  /** 新成员入超大群的回调, 此方法接收一个参数, 包含群信息和群成员信息 */
  onAddSuperTeamMembers?(result: NIMOnAddSuperTeamMembersRes): void;
  /** 有人出超大群的回调, 此方法接收一个参数, 包含群信息和被移除的群成员账号 */
  onRemoveSuperTeamMembers?(result: NIMOnRemoveSuperTeamMembersRes): void;
  /** 超大群解散的回调, 所有群成员均会收到该回调。此方法接收一个参数, 包含被解散的群id */
  onDismissSuperTeam?(result: NIMOnDismissSuperTeamRes): void;
  /** 移交超大群的回调, 此方法接收一个参数, 包含群信息和新老群主信息 */
  onTransferSuperTeam?(result: NIMOnTransferSuperTeamRes): void;
  /**
   * 是否同步群列表, 默认`true`. 如果传`false`就收不到群列表, 即不会收到`onteams`回调, 开发者后续可以调用获取群列表来[[NIM.getTeams|`获取群列表`]].
   * @default true
   */
  syncTeams?: boolean;
  /**
   * 是否同步额外的群信息, 默认`true`会同步额外的群信息, 目前包括
   * - 当前登录用户是否开启某个群的消息提醒 (SDK 只是存储了此信息, 具体用此信息来做什么事情完全由开发者控制)
   * - 调用接口 [[NIM.updateInfoInTeam|`NIM.updateInfoInTeam`]] 关闭/开启某个群的消息提醒
   * - 调用接口 [[NIM.notifyForNewTeamMsg|`NIM.notifyForNewTeamMsg`]] 来查询是否需要群消息通知
   * @default true
   */
  syncExtraTeamInfo?: boolean;
  /**
   * 同步群列表的回调, 会传入 [[NIMTeam|`群`]] 数组`teams`
   * - `teams` 的属性 `invalid` 包含退出的群
   */
  onteams?(teams: NIMOnteamsRes): void;
  /**
   * 当前登录用户在其它端[[NIM.createTeam|`创建群`]]后的回调, 会传入 [[NIMTeamMember|`群对象`]]
   */
  onsynccreateteam?(result: NIMOnsynccreateteamRes): void;
  /**
   * 是否同步群成员, 只有在 [[NIMInitConf.syncTeams|`NIMInitConf.syncTeams`]] = `true` 的时候才起作用,
   * - `false` 就不会同步群成员, 即不会收到 `onteammembers` 和 `onsyncteammembersdone` 回调, 开发者后续可以调用 [[NIM.getTeamMembers|`获取群成员`]] 来获取 [[NIMTeamMember|群成员]]
   * @default true
   */
  syncTeamMembers?: boolean;
  /** 同步群成员的回调, 一个群对应一个回调, 会传入 [[NIMTeamMember|群成员]] 数组 */
  onteammembers?(members: NIMOnteammembersRes): void;
  /**
   * 当 [[NIMInitConf.syncTeams|`NIMInitConf.syncTeams`]] 和 [[NIMInitConf.syncTeamMembers|`NIMInitConf.syncTeamMembers`]] 同时为 `true` 时, 会同步所有群的群成员, 当所有群的群成员同步结束时, 会调用此回调
   */
  onsyncteammembersdone?(result: NIMOnsynccreateteamRes): void;
  /**
   * 群成员信息更新后的回调, 会传入 [[NIMTeamMember|`群成员`]] 对象, 不过此时的信息是不完整的, 只会包括被更新的字段。当前登录帐号在其它端修改自己在群里面的昵称时也会收到此回调。
   */
  onupdateteammember?(result: NIMOnupdateteammemberRes): void;
  /**
   * 创建群的回调, 此方法接收一个参数, 包含群信息和群主信息
   */
  onCreateTeam?(result: NIMOnCreateTeamRes): void;
  /**
   * 更新群的回调, 此方法接收一个参数, 更新后的群信息
   */
  onUpdateTeam?(result: NIMOnUpdateTeamRes): void;
  /**
   * 新成员入群的回调, 此方法接收一个参数, 包含群信息和群成员信息
   */
  onAddTeamMembers?(result: NIMOnAddTeamMembersRes): void;
  /**
   * 有人出群的回调, 此方法接收一个参数, 包含群信息和群成员账号
   */
  onRemoveTeamMembers?(result: NIMOnRemoveTeamMembersRes): void;
  /**
   * 更新群管理员的回调, 此方法接收一个参数, 包含群信息和管理员信息
   */
  onUpdateTeamManagers?(result: NIMOnUpdateTeamManagersRes): void;
  /**
   * 解散群的回调, 此方法接收一个参数, 包含被解散的群id
   */
  onDismissTeam?(result: NIMOnDismissTeamRes): void;
  /**
   * 移交群的回调, 此方法接收一个参数, 包含群信息和新老群主信息
   */
  onTransferTeam?(result: NIMOnTransferTeamRes): void;
  /**
   * 更新群成员禁言状态的回调, 此方法接收一个参数, 包含群信息和禁言状态信息
   */
  onUpdateTeamMembersMute?(result: NIMOnUpdateTeamMembersMuteRes): void;
  /**
   * 是否同步会话的未读数
   * - 如果选择同步
   *    + 那么在一个端读过的会话在其它端也会被标记为已读
   *    + 在调用 [[NIM.setCurrSession|`NIM.setCurrSession`]] 的时候 SDK 会自动同步一次未读数, 此后如果收到当前会话的消息, 需要手动调用 [[NIM.resetSessionUnread|`NIM.resetSessionUnread`]] 来同步未读数
   * @default false
   */
  syncSessionUnread?: boolean;
  /**
   * 同步最近会话列表回调, 会传入 [[NIMSession|`会话`]] 列表, 按 [[NIMSession.updateTime|`时间`]] 正序排列, 即最近聊过天的放在列表的最后面。
   */
  onsessions?(result: NIMOnsessionsRes): void;
  /**
   * 更新会话的回调, 会传入会话, 以下情况会收到此回调
   * - `收到消息`  [[NIMInitConf.onmsg|`NIMInitConf.onmsg`]]
   * - `发送消息` [[NIM.sendText|`NIM.sendText`]]、[[NIM.sendCustomMsg|`NIM.sendCustomMsg`]]
   * - `设置当前会话` [[NIM.setCurrSession|`NIM.setCurrSession`]]
   * - `重置会话未读数` [[NIM.resetSessionUnread|`NIM.resetSessionUnread`]]
   */
  onupdatesession?(result: NIMOnupdatesessionRes): void;
  /**
   * 是否要忽略某条通知类消息, 该方法会接收一个消息对象, 如果该方法返回 true, 那么 SDK 将忽略此条通知类消息
   * @returns 是否忽略
   */
  shouldIgnoreNotification?(sysMsg: NIMSystemMessage): boolean;
  /**
   * 是否要忽略某消息。该方法会接收一个消息对象，如果该方法返回 true, 那么 SDK 将忽略此条消息（不计未读数，不当lastMsg，不存数据库，不触发onmsg通知）
   * @returns 是否忽略
   */
  shouldIgnoreMsg?(msg: NIMMessage): boolean;

  /**
   * 是否群通知消息记未读
   * - TODO: 未完成
   */
  shouldCountTeamNotifyUnread?(result: unknown): boolean;
  /**
   * 是否同步漫游消息, 默认 `true`. 如果传 `false` 就收不到漫游消息, 即不会收到 [[NIMInitConf.onroamingmsgs|`NIMInitConf.onroamingmsgs`]] 回调.
   * @default true
   */
  syncRoamingMsgs?: boolean;
  /**
   * 是否额外同步大群漫游消息, 默认 `true` . 如果传 `false` 就不会收到超大群的 [[NIMInitConf.onroamingmsgs|`NIMInitConf.onroamingmsgs`]] 回调.
   */
  syncSuperTeamRoamingMsgs?: boolean;
  /**
   * 同步漫游消息的回调, 每个会话对应一个回调, 会传入 [[NIMMessage|`消息`]] 数组
   */
  onroamingmsgs?(msgs: NIMOnroamingmsgsRes): void;
  /**
   * 同步离线消息的回调, 每个会话对应一个回调, 会传入 [[NIMMessage|`消息`]] 数组
   */
  onofflinemsgs?(msgs: NIMOnofflinemsgsRes): void;
  /**
   * 收到消息的回调, 会传入 [[NIMMessage|`消息`]] 对象
   * - 当前登录帐号在其它端发送消息之后也会收到此回调, 注意此时消息对象的 [[NIMMessage.from|`from`]] 字段就是当前登录的帐号
   */
  onmsg?(msg: NIMMessage): void;
  /**
   * 是否同步已读回执时间戳, 默认 `true`. 如果传 `false` 就收不到已读回执时间戳.
   * @default true
   */
  syncMsgReceipts?: boolean;
  /**
   * 同步离线系统通知的回调, 会传入 [[NIMSystemMessage|`系统通知`]] 数组
   */
  onofflinesysmsgs?(result: NIMSystemMessage[]): void;
  /**
   * 同步漫游系统通知的回调, 会传入 [[NIMSystemMessage|`系统通知`]] 数组
   */
  onroamingsysmsgs?(result: NIMSystemMessage[]): void;
  /**
   * 收到系统通知的回调, 会传入 [[NIMSystemMessage|`系统通知`]]
   */
  onsysmsg?(result: NIMSystemMessage): void;
  /**
   * 更新系统通知后的回调, 会传入 [[NIMSystemMessage|`系统通知`]]
   * - 以下情况会收到此回调
   *    + `通过好友申请`  `拒绝好友申请`  `接受入群邀请`  `拒绝入群邀请`  `通过入群申请`  `拒绝入群申请`
   * - 这些操作的发起方会收到此回调, 接收被更新的系统通知, 根据操作的类型系统通知会被更新为下面两种状态
   *    + `"passed"` 已通过
   *    + `"rejected"`  已拒绝
   */
  onupdatesysmsg?(result: NIMOnupdatesysmsgRes): void;
  /**
   * 收到系统通知未读数的回调
   * - SDK 会管理内建系统通知的未读数, 此回调接收的对象包括以下字段
   *  - `total`: 总共的未读数
   *  - `friend`: 所有跟好友相关的系统通知的未读数
   *  - `addFriend`: 直接加为好友的未读数
   *  - `applyFriend`: 申请加为好友的未读数
   *  - `passFriendApply`: 通过好友申请的未读数
   *  - `rejectFriendApply`: 拒绝好友申请的未读数
   *  - `deleteFriend`: 删除好友的未读数
   *  - `team`: 所有跟群相关的系统通知的未读数
   *  - `teamInvite`: 入群邀请的未读数
   *  - `rejectTeamInvite`: 接受入群邀请的未读数
   *  - `applyTeam`: 入群申请的未读数
   *  - `rejectTeamApply`: 拒绝入群申请的未读数
   */
  onsysmsgunread?(result: NIMOnsysmsgunreadRes): void;
  /** 更新系统通知未读数的回调 */
  onupdatesysmsgunread?(result: NIMOnupdatesysmsgunreadRes): void;
  /** 同步离线自定义系统通知的回调, 会传入[[NIMSystemMessage|系统通知]]数组 */
  onofflinecustomsysmsgs?(result: NIMOncustomsysmsgRes): void;
  /** 收到自定义系统通知的回调, 会传入[[NIMSystemMessage|系统通知]] */
  oncustomsysmsg?(result: NIMSystemMessage): void;
  /** 当上面各个同步（不包括下面的同步群成员）完成后, 会调用此回调；注意, SDK保证在`onsyncdone`调用的时候上面的同步肯定完成了, 但是不保证各个同步回调的顺序。 */
  onsyncdone?(result: NIMOnsyncdoneRes): void;
  /**
   * 收到单向撤回消息的回调, 会传入被删除的[[NIMMessage|消息]]数组
   * - 7.4.0 新增
   */
  onDeleteMsgSelf?(result: NIMMessage): void;
  /**
   * 收到快捷评论，会传入两个参数，分别是对应的消息和评论
   * - 7.6.0 新增
   */
  onQuickComment?(msg: NIMMessage, comment: NIMComment): void;
  /**
   * 收到删除了快捷评论，会传入两个参数，分别是对应的消息和评论
   * - 7.6.0 新增
   */
  onDeleteQuickComment?(msg: NIMMessage, comment: NIMComment): void;
  /**
   * 同步置顶会话列表, 会传入会话列表
   * - 7.6.0 新增
   */
  onStickTopSessions?(sesss: NIMSession[]): void;
  /**
   * 是否同步置顶会话
   * - 是否同步置顶会话，默认false，如果传true，则在有置顶会话时，可以收到onStickTopSessions回调，传false则不会
   * - 7.6.0 新增
   * @default false
   */
  syncStickTopSessions?: boolean;
  /**
   * 是否自动标记消息为已收到
   * - 默认情况下SDK在收到服务器推送过来的消息后, 会在将消息推给开发者时将消息标记为已读状态, 下次登录后就不会收到标记为已读的消息。
   *    + SDK通过`onofflinemsgs`、`onofflinesysmsgs`、[[NIMInitConf.onofflinecustomsysmsgs|`onofflinecustomsysmsgs`]] 等回调将离线消息推送给开发者
   *    + SDK通过`onmsg`、`onsysmsg`、`oncustomsysmsg`等回调将在线消息推送给开发者
   * - 如果开发者想控制标记消息为已收到的时机, 那么可以传`false`, 这样SDK就不会自动标记消息已读, 此时需要开发者在适当的时机调用相关的方法来标记消息为已读, 否则下次登录后还会收到未标记为已读的消息。\
   *    + 调用[[NIM.markSysMsgRead|`标记系统通知已读`]]来标记[[NIMSystemMessage|`系统通知`]]和[[NIMSystemMessage.type|`自定义系统通知`]]为已读状态
   * @default true
   */
  autoMarkRead?: boolean;
  /**
   * 是否使用本地数据库
   * - 在支持数据库的浏览器上 SDK 会将数据缓存到数据库中, 后续同步都是增量更新, 加快初始化速度
   * - 如果开发者不想使用数据库, 那么可以设置`db`为 `false` 来禁用数据库
   * @default true
   */
  db?: boolean;
  /**
   * 是否将动态图片缩略为静态图片，默认将动态图片缩略为静态图片
   * - 仅在 `cover` 和 `contain` 缩略模式下，才支持将动态图片缩略为动态图片，其他模式下只能缩略为静态图片
   * - 可以调用SDK的 [[NIM.thumbnailImage|`NIM.thumbnailImage`]]，[[NIM.processImage|`NIM.processImage`]] 等API生成图片的缩略图
   * @default true
   */
  thumbnailToStatic?: boolean;
  /**
   * 是否上报异常错误日志，可以将该项设为 `false` 来禁止上报错误日志
   * - SDK会将部分错误及相关信息上传至云信统计平台，方便开发者统计及排查线上错误
   * @default false
   */
  logReport?: boolean;

  /**
   * 监听所订阅的事件（需要额外开通）
   * - [相关文档](ttps://dev.yunxin.163.com/docs/product/IM即时通讯/SDK开发集成/Web开发集成/事件订阅?kw=onpushevents&pg=1&pid=0&#监听所订阅的事件)
   */
  onpushevents?(msgEvents: NIMMsgEvent[]): void;
  /**
   * 更新服务端会话在线多端同步回调。多端登录时，一端调用 [NIM.updateServerSession] 更新了服务端会话，其他端会收到该同步回调
   * - 7.0.0 支持
   */
  onSyncUpdateServerSession?(serverSession: NIMServerSession): void;
}


export namespace NIMInitConf {
  /**
   * 允许使用 [NIM.setOptions] 更新的配置
   */
  export interface AllowUpdateConf extends Partial<Pick<NIMInitConf, 'token'>>, Partial<EventHandlersConf> {

  }

  /**
   * 所有云信事件处理器配置
   */
  export interface EventHandlersConf extends PickIncludeVal<NIMInitConf, Function> {

  }

}

/**
 * 连接建立后的回调
 * - [[NIMInitConf.onconnect|`NIMInitConf.onconnect`]]
 */
export interface NIMOnconnectRes {
  /** 上次登录的设备的设备号 */
  lastLoginDeviceId: string;
  /**
   * ★当前登录的设备ID
   * - 非云信官方返回(通过修改云信的SDK实现)
   */
  currentDeviceId: string;
  /** 本次登录的国家 */
  country: string;
  /** 客户端IP */
  ip: string;
  /** 客户端端口 */
  port: string;
  /** 本次登录的连接号 */
  connectionId: string;
}

/**
 * 即将重连时回调的对象
 * - [[NIMInitConf.onwillreconnect|`NIMInitConf.onwillreconnect`]]
 */
export interface NIMOnwillreconnectRes {
  /** 距离下次重连的时间 */
  duration: number;
  /** 重连尝试的次数 */
  retryCount: number;
}

/**
 * 断开连接后的回调
 * - [[NIMInitConf.ondisconnect|`NIMInitConf.ondisconnect`]]
 */
export type NIMOndisconnectRes = {
  /** 出错时的错误码, 可能为空 */
  code: NullOr<Exclude<NIMDisconnectCode, NIMDisconnectCode.kicked>>;
} | {
  code: NIMDisconnectCode.kicked;
  /** 被踢的原因 */
  reason: NIMKickReason;
  /** 文字描述的被踢的原因 */
  message: string;
  /** 被哪种设备踢的 */
  from: NIMClientType;
};

/** 断开连接的 `code` */
export const enum NIMDisconnectCode {
  /** 账号或者密码错误, 请跳转到登录页面并提示错误 */
  _302 = 302,
  /** 重复登录, 已经在其它端登录了, 请跳转到登录页面并提示错误 */
  _417 = 417,
  /** 被踢 */
  kicked = 'kicked',
  /** 自动登出 */
  logout = 'logout',
}




/** 被踢端的原因 */
export const enum NIMKickReason {
  /** 不允许同一个帐号在多个地方同时登录 */
  samePlatformKick = 'samePlatformKick',
  /** 被服务器踢了 */
  serverKick = 'serverKick',
  /** 被其它端踢了 */
  otherPlatformKick = 'otherPlatformKick',
}

/**
 * 发信错误时回调
 * - [[NIMInitConf.onerror|`NIMInitConf.onerror`]]
 */
export interface NIMOnerrorResRes extends NIMError {

}

/**
 * 多端登录状态变化的回调, 会收到 [[NIMLoginPort|`登录端`]] 列表,
 * - [[NIMInitConf.onloginportschange|`NIMInitConf.onloginportschange`]]
 */
export interface NIMOnloginportschangeRes extends Array<NIMLoginPort> {

}

/**
 * 同步黑名单的回调
 * - [[NIMInitConf.onblacklist|`NIMInitConf.onblacklist`]]
 */
export interface NIMOnblacklistRes extends Array<NIMRelation> {
  /** 被删除的黑名单列表 */
  invalid: NIMRelation[];
}

/**
 * 当前登录用户在其它端加入黑名单/从黑名单移除后的回调, 会传入一个参数, 包含两个字段
 * - [[NIMInitConf.onsyncmarkinblacklist|`NIMInitConf.onsyncmarkinblacklist`]]
 */
export interface NIMOnsyncmarkinblacklistRes extends NIMMarkInfo {

}

/**
 * 同步静音列表的回调, 会传入静音列表 mutelist
 * - [[NIMInitConf.onmutelist|`NIMInitConf.onmutelist`]]
 */
export interface NIMOnmutelistRes extends Array<NIMRelation> {
  invalid: NIMRelation[];
}

/**
 * 当前登录用户在其它端加入静音列表/从静音列表移除后的回调, 会传入一个参数, 包含两个字段
 * - [[NIMInitConf.onsyncmarkinmutelist|`NIMInitConf.onsyncmarkinmutelist`]]
 */
export interface NIMOnsyncmarkinmutelistRes extends NIMMarkInfo {

}

/**
 * 同步好友列表的回调, 会传入好友列表。没有好友时，使用数据库会调用回调传空数组，否则不回调。
 * - [[NIMInitConf.onfriends|`NIMInitConf.onfriends`]]
 */
export interface NIMOnfriendsRes extends Array<NIMFriend> {

}

/**
 * 当前登录用户在其它端进行好友相关的操作后的回调
 * + 操作包括
 *  - 直接加为好友
 *  - 申请加为好友
 *  - 通过好友申请
 *  - 拒绝好友申请
 *  - 删除好友
 *  - 更新好友
 * + [[NIMInitConf.onsyncfriendaction|`NIMInitConf.onsyncfriendaction`]]
 */
export type NIMOnsyncfriendactionRes = {
  type: NIMFriendActionType.addFriend;
  /** 被直接加为好友的账号 */
  account: NIMFriend['account'];
  /** 被直接加为好友的好友对象 */
  friend: NIMFriend;
  /** 附言 */
  ps: NonNullable<NIMSystemMessage['ps']>;
} | {
  type: NIMFriendActionType.applyFriend;
  /** 被申请加为好友的账号 */
  account: NIMFriend['account'];
  /** 附言 */
  ps: NonNullable<NIMSystemMessage['ps']>;
} | {
  type: NIMFriendActionType.passFriendApply;
  /** 被通过好友申请的账号 */
  account: NIMFriend['account'];
  /** 被通过好友申请的好友对象 */
  friend: NIMFriend;
  /** 附言 */
  ps: NonNullable<NIMSystemMessage['ps']>;
} | {
  type: NIMFriendActionType.rejectFriendApply;
  /** 被拒绝好友申请的账号 */
  account: NIMFriend['account'];
  /** 附言 */
  ps: NonNullable<NIMSystemMessage['ps']>;
} | {
  type: NIMFriendActionType.deleteFriend;
  /** 被删除好友的账号 */
  account: NIMFriend['account'];
} | {
  type: NIMFriendActionType.updateFriend;
  /** 被更新的好友对象 */
  friend: NIMFriend;
};

/**
 * 好友操作是回调的 type
 * - [[NIMInitConf.onsyncfriendaction|`NIMInitConf.onsyncfriendaction`]]
 */
export const enum NIMFriendActionType {
  /** 直接加为好友 */
  addFriend = 'addFriend',
  /** 申请加为好友 */
  applyFriend = 'applyFriend',
  /** 通过好友申请 */
  passFriendApply = 'passFriendApply',
  /** 拒绝好友申请 */
  rejectFriendApply = 'rejectFriendApply',
  /** 删除好友 */
  deleteFriend = 'deleteFriend',
  /** 更新好友 */
  updateFriend = 'updateFriend',
}

/**
 * 同步登录 [[NIMUser|`用户名片`]] 的回调, 会传入 [[NIMUser|`用户名片`]]
 * - [[NIMInitConf.onmyinfo|`NIMInitConf.onmyinfo`]]
 */
export interface NIMOnmyinfoRes extends NIMUser {

}

/**
 * 当前登录用户在其它端修改自己的个人名片之后的回调, 会传入 [[NIMUser|`用户名片`]]
 * - [[NIMInitConf.onupdatemyinfo|`NIMInitConf.onupdatemyinfo`]]
 */
export interface NIMOnupdatemyinfoRes extends NIMUser {

}

/**
 * 同步好友 [[NIMUser|`用户名片`]] 的回调, 会传入 [[NIMUser|`用户名片`]] 数组
 * - [[NIMInitConf.onusers|`NIMInitConf.onusers`]]
 */
export interface NIMOnusersRes extends Array<NIMUser> {

}

/**
 * [[NIMUser|`用户名片`]] 更新后的回调, 会传入 [[NIMUser|`用户名片`]]
 * - [[NIMInitConf.onupdateuser|`NIMInitConf.onupdateuser`]]
 */
export interface NIMOnupdateuserRes extends NIMUser {

}

/**
 * 同步超大群列表的回调, 会传入超大群数组
 * - [[NIMInitConf.onSuperTeams|`NIMInitConf.onSuperTeams`]]
 */
export interface NIMOnSuperTeamsRes extends Array<NIMSuperTeam> {

}

/**
 * 当前登录者创建超大群后的回调, 会传入超大群
 * - [[NIMInitConf.onSyncCreateSuperTeam|`NIMInitConf.onSyncCreateSuperTeam`]]
 */
export interface NIMOnSyncCreateSuperTeamRes extends NIMSuperTeam {

}

/**
 * 更新超大群的回调, 此方法接收一个参数, 更新后的群信息
 * - [[NIMInitConf.onUpdateSuperTeam|`NIMInitConf.onUpdateSuperTeam`]]
 */
export interface NIMOnUpdateSuperTeamRes extends NIMSuperTeam {

}

/**
 * 群成员信息更新后的回调, 会传入超大群群成员对象, 不过此时的信息是不完整的, 只会包括被更新的字段。当前登录帐号在其它端修改自己在群里面的昵称时也会收到此回调
 * - [[NIMInitConf.onUpdateSuperTeamMember|`NIMInitConf.onUpdateSuperTeamMember`]]
 */
export interface NIMOnUpdateSuperTeamMemberRes extends NIMSuperTeamMember {

}


/**
 * 新成员入超大群的回调, 此方法接收一个参数, 包含群信息和群成员信息
 * - [[NIMInitConf.onAddSuperTeamMembers|`NIMInitConf.onAddSuperTeamMembers`]]
 * - TODO: 文档模糊，未知实际返回结构
 */
export interface NIMOnAddSuperTeamMembersRes {
  team: NIMSuperTeam;
  accounts: NIMSuperTeamMember['account'];
  members: NIMSuperTeamMember[];
}

/**
 * 有人出超大群的回调, 此方法接收一个参数, 包含群信息和被移除的群成员账号
 * - [[NIMInitConf.onRemoveSuperTeamMembers|`NIMInitConf.onRemoveSuperTeamMembers`]]
 */
export interface NIMOnRemoveSuperTeamMembersRes {
  team: NIMSuperTeam;
  accounts: NIMSuperTeamMember['account'];
}


/**
 * 超大群解散的回调, 所有群成员均会收到该回调。此方法接收一个参数, 包含被解散的群id
 * - [[NIMInitConf.onDismissSuperTeam|`NIMInitConf.onDismissSuperTeam`]]
 */
export interface NIMOnDismissSuperTeamRes {
  teamId: NIMSuperTeam['teamId'];
}

/**
 * 移交超大群的回调, 此方法接收一个参数, 包含群信息和新老群主信息
 * - [[NIMInitConf.onTransferSuperTeam|`NIMInitConf.onTransferSuperTeam`]]
 * - TODO: 文档模糊，未知实际返回结构
 */
export interface NIMOnTransferSuperTeamRes extends Array<NIMTeam> {

}


/**
 * 同步群列表的回调, 会传入群数组teams
 * - [[NIMInitConf.onteams|`NIMInitConf.onteams`]]
 */
export interface NIMOnteamsRes extends Array<NIMTeam> {
  invalid: NIMTeam[];
}

/**
 * 当前登录用户在其它端创建群后的回调, 会传入群对象
 * - [[NIMInitConf.onsynccreateteam|`NIMInitConf.onsynccreateteam`]]
 */
export interface NIMOnsynccreateteamRes extends NIMTeam {

}

/**
 * 同步群成员的回调, 一个群对应一个回调, 会传入群成员数组
 * - [[NIMInitConf.onteammembers|`NIMInitConf.onteammembers`]]
 */
export interface NIMOnteammembersRes {
  teamId: NIMTeamMember['teamId'];
  members: NIMTeamMember[];
}


/**
 * 当syncTeams和syncTeamMembers同时为true时, 会同步所有群的群成员, 当所有群的群成员同步结束时, 会调用此回调
 * - [[NIMInitConf.onsyncteammembersdone|`NIMInitConf.onsyncteammembersdone`]]
 */
export type NIMOnsyncteammembersdoneRes = void;


/**
 * 群成员信息更新后的回调, 会传入群成员对象, 不过此时的信息是不完整的, 只会包括被更新的字段。当前登录帐号在其它端修改自己在群里面的昵称时也会收到此回调。
 * - [[NIMInitConf.onupdateteammember|`NIMInitConf.onupdateteammember`]]
 */
export interface NIMOnupdateteammemberRes extends NIMTeamMember {

}


/**
 * 创建群的回调, 此方法接收一个参数, 包含群信息和群主信息
 * - [[NIMInitConf.onCreateTeam|`NIMInitConf.onCreateTeam`]]
 */
export interface NIMOnCreateTeamRes extends NIMTeam {

}

/**
 * 更新群的回调, 此方法接收一个参数, 更新后的群信息
 * - [[NIMInitConf.onUpdateTeam|`NIMInitConf.onUpdateTeam`]]
 */
export interface NIMOnUpdateTeamRes extends NIMTeam {

}

/**
 * 新成员入群的回调, 此方法接收一个参数, 包含 [[NIMTeam|`群`]]  信息和 [[NIMTeam|`群成员信息`]]
 * - [[NIMInitConf.onAddTeamMembers|`NIMInitConf.onAddTeamMembers`]]
 */
export interface NIMOnAddTeamMembersRes {
  team: NIMTeam;
  accounts: Array<NIMTeamMember['account']>;
  members: NIMTeamMember[];
}

/**
 * 有人出群的回调, 此方法接收一个参数, 包含 [[NIMTeam|`群`]] 信息和 [[NIMTeamMember.account|`群成员账号`]]
 * - [[NIMInitConf.onRemoveTeamMembers]]
 */
export interface NIMOnRemoveTeamMembersRes {
  team: NIMTeam;
  accounts: Array<NIMTeamMember['account']>;
}

/**
 * 更新群管理员的回调, 此方法接收一个参数, 包含 [[NIMTeam|`群`]] 信息和 `管理员信息`
 * - [[NIMInitConf.onUpdateTeamManagers]]
 * - TODO: 文档模糊，未知实际返回结构
 */
export interface NIMOnUpdateTeamManagersRes {
  team: NIMTeam;
  accounts: Array<NIMTeamMember['account']>;
  isManager: boolean;
  members: NIMTeamMember[];
}

/**
 * 解散群的回调, 此方法接收一个参数, 包含被解散的 [[NIMTeam.teamId|`群id`]]
 * - [[NIMInitConf.onDismissTeam]]
 */
export interface NIMOnDismissTeamRes {
  teamId: NIMTeam['teamId'];
}

/**
 * 移交群的回调, 此方法接收一个参数, 包含群信息和新老群主信息
 * - [[NIMInitConf.onTransferTeam]]
 */
export interface NIMOnTransferTeamRes {
  team: NIMTeam;
  from: NIMTeamMember['account'];
  to: NIMTeamMember['account'];
}


/**
 * 更新群成员禁言状态的回调, 此方法接收一个参数, 包含群信息和禁言状态信息
 * - [[NIMInitConf.onUpdateTeamMembersMute]]
 */
export interface NIMOnUpdateTeamMembersMuteRes {
  team: NIMTeam;
  accounts: Array<NIMTeamMember['account']>;
  members: NIMTeamMember[];
  mute: boolean;
}

/**
 * 同步最近会话列表回调, 会传入 [[NIMSession|`会话`]] 列表, 按时间正序排列, 即最近聊过天的放在列表的最后面。
 * - [[NIMInitConf.onsessions]]
 */
export interface NIMOnsessionsRes extends Array<NIMSession> {

}

/**
 * 更新会话的回调, 会传入 [[NIMSession|`会话`]],
 * - [[NIMInitConf.onupdatesession]]
 */
export interface NIMOnupdatesessionRes extends NIMSession {

}


/**
 * 同步漫游消息(包括超大群漫游消息和其他漫游消息)的回调, 每个会话对应一个回调, 会传入消息数组
 * - [[NIMInitConf.onroamingmsgs]]
 */
export interface NIMOnroamingmsgsRes {
  msgs: NIMMessage[];
}

/**
 * 同步离线消息的回调, 每个会话对应一个回调, 会传入消息数组
 * - [[NIMInitConf.onofflinemsgs]]
 */
export interface NIMOnofflinemsgsRes {
  msgs: NIMMessage[];
}




/**
 * 同步离线系统通知的回调, 会传入系统通知数组
 * - [[NIMInitConf.onofflinesysmsgs]]
 */
export interface NIMOnofflinesysmsgsRes extends Array<NIMSystemMessage> {

}


/**
 *  同步漫游系统通知的回调, 会传入系统通知数组
 * - [[NIMInitConf.onroamingsysmsgs]]
 */
export interface NIMOnroamingsysmsgsRes {

}


/**
 * 收到系统通知的回调, 会传入系统通知
 * - [[NIMInitConf.onsysmsg]]
 */
export interface NIMOnsysmsgRes extends NIMSystemMessage {

}


/**
 * 更新系统通知后的回调, 会传入系统通知
 * - [[NIMInitConf.onupdatesysmsg]]
 */
export interface NIMOnupdatesysmsgRes extends NIMSystemMessage {

}

/**
 * 收到系统通知未读数的回调
 * - [[NIMInitConf.onsysmsgunread]]
 */
export interface NIMOnsysmsgunreadRes {
  /** 总共的未读数 */
  total: number;
  /** 所有跟好友相关的系统通知的未读数 */
  friend: number;
  /** 直接加为好友的未读数 */
  addFriend: number;
  /** 申请加为好友的未读数 */
  applyFriend: number;
  /** 通过好友申请的未读数 */
  passFriendApply: number;
  /** 拒绝好友申请的未读数 */
  rejectFriendApply: number;
  /** 删除好友的未读数 */
  deleteFriend: number;
  /** 所有跟群相关的系统通知的未读数 */
  team: number;
  /** 入群邀请的未读数 */
  teamInvite: number;
  /** 接受入群邀请的未读数 */
  rejectTeamInvite: number;
  /** 入群申请的未读数 */
  applyTeam: number;
  /** 拒绝入群申请的未读数 */
  rejectTeamApply: number;
}


/**
 * 更新系统通知未读数的回调
 * - [[NIMInitConf.onupdatesysmsgunread]]
 * - TODO: 文档模糊，未知实际返回结构
 */
export interface NIMOnupdatesysmsgunreadRes {

}

/**
 * 同步离线自定义系统通知的回调, 会传入系统通知数组
 * - [[NIMInitConf.onofflinecustomsysmsgs]]
 */
export interface NIMOnofflinecustomsysmsgsRes extends Array<NIMSystemMessage> {

}

/**
 * 收到自定义系统通知的回调, 会传入系统通知
 * - [[NIMInitConf.oncustomsysmsg]]
 */
export interface NIMOncustomsysmsgRes extends NIMSystemMessage {

}


/**
 * 当上面各个同步（不包括下面的同步群成员）完成后, 会调用此回调；注意, SDK保证在onsyncdone调用的时候上面的同步肯定完成了, 但是不保证各个同步回调的顺序
 * - [[NIMInitConf.onsyncdone]]
 */
export type NIMOnsyncdoneRes = void;

