export { Messages } from '../constants/messages';
export { ThemeType } from '../theme';
import { ITheme } from 'xterm';
import { EditorView } from '~/lib/codemirror-editor/src';

export type InsertCodeLineCode = number | 'TOP' | 'BOTTOM';
export interface IExtralAction {
  replaceSelection?: Array<any> | string;
}
export type ContextMenuTypeItem = {
  id?: number;
  isCheck?: boolean;
  isAi?: boolean;
  isDone?: boolean;
  isRepalceRange?: boolea;
  action: string;
  noActionCheck?: boolean; // / 答题区需要坚持隐藏，只读，答题区域内等情况不能设置
  codeAction?: 'append' | 'replace' | undefined;
  text: string;
  icon: string;
  iconLabel: string;
  commentStartLabel: string;
  // commentEndLabel: string;
  commentTips?: string;
  hideCodeBlock: boolean;
  flag?: string;
};
export type CodeSnippetOption = {
  template: string;
  option: {
    label: string;
    detail?: string;
  };
};
export type TranslateTypeOption = {
  [x: string]: ReactI18NextChild | Iterable<ReactI18NextChild>;
  [typeof I18nLanguageType]: string;
};
export type TranslateType = Record<string, Record<TranslateTypeOption>>;
export type CodeSnippetType = Record<string, Array<CodeSnippetOption>>;
export type FileHeaderType = {
  className?: string;
  icon: {
    className: string;
    tips?: TranslateTypeOption;
    action?: () => void;
  };
  tipsDuration?: number;
  showTips?: boolean;
  label?: TranslateTypeOption;
  labelAction?: {
    label: TranslateTypeOption;
    action: () => void;
    tips?: TranslateTypeOption;
  };
};

export type IOverrideParams = {
  // 选择区域会包含多个答题区
  ids: Array<string>;
  action: string;
};

export type ContextMenuType = {
  handleSelect: (
    e: any,
    callback?: (data: any, extralAction: IExtralAction) => void,
  ) => void;
  items: Array<ContextMenuTypeItem>;
  // 答题区tooltip标题
  title?: string;
  // 在已设置答题区区域内点击右击菜单，菜单和执行函数回调
  overrideItems?: Array<Pick<ContextMenuTypeItem, 'action' | 'text'>>;
  handleOverride?: (params: IOverrideParams) => void;
};
export type ResultType = {
  status: boolean;
  message: string;
};
/**
 * SDK内部组件名
 */
export type ComponentType =
  | 'Tree'
  | 'Editor'
  | 'Browser'
  | 'Console'
  | 'Shell'
  | 'MarkdownPreview';

/**
 * Playground状态类型
 */
export type PlaygroundStatus = 'EMPTY' | 'ACTIVE' | 'INACTIVE';
/**
 * Docker运行状态
 */
export type DockerStatus = 'RUNNING' | 'STOP' | 'DEBUG_RUNNING';
/**
 * 用于挂载组件的的配置接口
 */
export interface Component {
  /** SDK内部组件挂载的dom元素选择器，如“.dom-classname”,"#dom-id","div span" */
  container: string | HTMLElement | Element;
  /** SDK内部组件名 */
  item: ComponentType;
  /** 传给SDK内部组件的props */
  // props?: any;
}

/**
 * SDK消息监听数据类型
 */
export type Message = {
  /** 消息类型 */
  name: Messages;
  /** 消息内容 */
  payload?: any;
  /** 错误信息 */
  error?: string;
};

/**
 * xterm样式设置
 */
export interface IXtermFontStyle {
  fontSize?: number;
  lineHeight?: number;
  fontFamily?: string;
}
export interface XtermStyleType {
  console?: ITheme;
  terminal?: ITheme;
  claudecode?: ITheme;
  consoleStyle?: IXtermFontStyle;
  terminalStyle?: IXtermFontStyle;
  claudecodeStyle?: IXtermFontStyle;
}
export type ContextMenuItem = {
  text: {
    [x: string]: ReactI18NextChild | Iterable<ReactI18NextChild>;
    [typeof I18nLanguageType]: string;
  }; // 菜单名称
  shortcutKey?: string; // 快捷键名称
  actionName?: string; // 执行指令名称
  actionFun?: (
    view: EditorView,
    commands,
    firstNum?: number,
    lastNum?: number,
  ) => void; // 自定义逻辑方法
  actionShortcutKey?: string; // 触发的快捷键的名称
  className?: string; // 自定义样式
  textClassName?: string;
  shortcutClassName?: string;
  withCodeFlag?: boolean;
};

export type ReportHighlightCache = { [key: string]: LineInfo[] };
export type ReportHighlightFileInfo = {
  path: string;
  baseContent: string;
  arr: number[];
};
export interface IReportHighlightData {
  list: ReportHighlightFileInfo[];
  originDockerId: string;
  cache?: ReportHighlightCache;
}
export interface IReplayFileChangeLogs {
  [x: string]: string[];
}

export type ContextMenu = Array<Array<ContextMenuItem>>;
/**
 * SDK构造函数参数
 * @category PaaSOptions [Required]
 */
export interface PaaSOptions {
  /** Unit Test Mock Socket */
  socket?: any;
  /** 票 */
  ticket: string;
  /** 租户id */
  tenantId: string;
  /** 用户信息 */
  userInfo: UserInfo;
  /** 可选, 默认连接到 www.1024paas.com */
  paasDomain?: string;
  /** SDK主题，默认dark */
  themeType?: ThemeType;
  /** SDK国际化语言，默认ZH */
  i18nLanguage?: I18nLanguageType;
  /** 是否插入CRDT数据 - 1.是否开启回放功能 */
  isInsertCrdt?: boolean;
  /** 是否兼容遗留的markdown数学公式解析 - false不兼容(标准语法)  true(标准语法 + `$ $`)*/
  isLegacyMarkdownMath?: boolean;
  /** 回放模式：两针间隔最大时长触发事件参数 */
  triggerEventForMaxTimespan?: number;
  /** websocket最大尝试重连次数：5 */
  reconnectMaxTimes?: number;
  /** xterm样式配置 */
  xtermStyle?: XtermStyleType;
  /** 是否开启debug模式 */
  isOpenDebugMode?: boolean;
  /** 是否开启sentry */
  enableSentry?: boolean;
  /** 默认打开文件路径 */
  defaultOpenFiles?: string[];
  defaultLspLang?: string[];
  /** 业务指定默认打开文件路径 */
  specialOpenFile?: string;
  /** 是否打开LSP的诊断 */
  openLspDiagnostic?: boolean;
  /** 对指定文件采用指定语法高亮 */
  specialFileHighlight?: Array<ISpecialFileHighlight>;
  /** 回放指定为空白帧的时间间隔，单位 为 s(秒)， 1 为1s 1000 */
  noFrameSpan?: number;
  /** 支持日志上报业务方 */
  customLog?: (level: string, ...args) => void;
  /** 回放时的播放速度参数 */
  speedOption?: number[];
  // 是否针对非AI用户修改的代码进行拆分代码块
  isSplitCode?: boolean;
  /** 是否记录Browser 回放数据 */
  recordBrowser?: boolean;
  /** 是否持久化保存RRWEB 数据 */
  persistenceWebData?: boolean;
  /** 支持初始化配置全局设置 */
  globalConfig?: GlobalConfig;
  /** 是否自定义文件树操作*/
  customFileTreeAction?: boolean;
  /** 是否自定义MD 图片预览事件*/
  customImagePreview?: boolean;
  hideEditorToolTip?: boolean;
  hideEditorContextMenu?: boolean;
  /** 用于控制是否显示RRWEB的播放控制器，用于调试 */
  showRRwebController?: boolean;
  focusEditorPosition?: InsertCodeLineCode;
  /** 是否显示文件修改的Icon */
  showModifyIcon?: boolean;
  aiCodeMenu?: ContextMenu;
  contextMenu?: ContextMenu;
  /** CodeMirror Plugin */
  editorPlugins?: any[];
  /** 文件高亮数据配置参数，用于评卷报告  */
  reportHighlightData?: IReportHighlightData;
  /** 文件变更日志 */
  replayFileChangeLogs?: IReplayFileChangeLogs;
  /** 编辑器空白页面的配置 */
  editorBlankContent?: string;
}

export type ISpecialFileHighlight = {
  fileName: string;
  languageType: ICodeLanguage;
};

export type ICodeLanguage =
  | 'javascript'
  | 'typescript'
  | 'ruby'
  | 'lua'
  | 'go'
  | 'swift'
  | 'vb'
  | 'kotlin'
  | 'csharp'
  | 'verilog'
  | 'vhdl'
  | 'dart'
  | 'clojure'
  | 'coffeescript'
  | 'erlang'
  | 'hs'
  | 'objectiveC'
  | 'perl'
  | 'scala'
  | 'r'
  | 'shell'
  | 'dockerfile'
  | 'gas'
  | 'asm'
  | 'oCaml'
  | 'yaml'
  | 'elixir'
  | 'html'
  | 'css'
  | 'cpp'
  | 'c'
  | 'java'
  | 'json'
  | 'markdown'
  | 'php'
  | 'python'
  | 'sql'
  | 'rust'
  | 'xml';

export type EditorMode = 'default' | 'vim' | 'emacs';

export type EditorIndentMode = 'space' | 'tab';

/**
 * starting 正在启动
 * executing正在执行
 * executed 执行完成
 * stop停止
 */
export type IDebugStatus = 'starting' | 'executing' | 'executed' | 'stop';

// 国际化语言类型
export enum I18nLanguageType {
  /** 中文 */
  ZH = 'ZH',
  /** 英文 */
  EN = 'EN',
}

// 资源列表
export interface I18nResourcesType {
  language: I18nLanguageType;
  resource: any;
}

export type GlobalConfig = {
  editorMode?: EditorMode;
  editorTabSize?: number | 'auto';
  editorWordWrap?: boolean;
  fontSize?: string;
  editorIndentMode?: EditorIndentMode;
  openDiagnostic?: boolean;

  markdownPreview?: {
    isBlank?: boolean;
    iframeWidth?: string;
    iframeHeight?: string;
  };
};

export type BaseConfig = {
  hideEditorToolTip?: boolean;
  hideEditorContextMenu?: boolean;
};
export type Config = {
  disableEditable?: boolean;
  disableFileTreeAction?: boolean;
};

/**
 * 这是应用程序入口
 *
 * 使用如下:
 * ```ts
 *    let options = {...};
 *    let dao = new DaoPaaS(options);
 * ```
 */
export interface IDaoPaaS {
  /** 主题类型 */
  themeType: ThemeType;
  /** 国际化语言 */
  i18nLanguage: I18nLanguageType;
  /** sdk版本 */
  sdkVersion: string;
  /** 打开LSP服务诊断的开关 */
  /**
   * 错误消息侦听器.
   * @param {(error: Message) => void} callback 回调函数
   * @event
   */
  onError?: (callback: (error: Message) => void) => void;
  /**
   * 移除错误消息侦听器.
   * @param {(error: Message) => void} callback 回调函数
   * @event
   */
  removeError?: (callback: (error: Message) => void) => void;
  /**
   * 消息侦听器.
   * @param {(message: Message) => void} callback 回调函数
   * @event
   */
  onMessage?: (callback: (message: Message) => void) => void;
  /**
   * 移除消息侦听器.
   * @param {(message: Message) => void} callback 回调函数
   * @event
   */
  removeMessage?: (callback: (message: Message) => void) => void;
  /**
   * 页面卸载的时候需要销毁实例和相关的缓存数据
   */
  dispose(): void;
  /**
   * 取消用户跟随
   * @param { UserInfo } user 用户信息
   * @param { (userInfo: UserInfo) => void } callback 回调函数
   */
  unFollowUser(user: UserInfo, callback: (userInfo: UserInfo) => void): void;
  /**
   * 用户跟随
   * @param { string } agentUserId 用户id
   * @param { (userInfo: UserInfo) => void } callback 回调函数
   */
  followUser(agentUserId: string, callback: (userInfo: UserInfo) => void): void;

  /**
   * 准备回放数据,回放摘要信息到达后,会触发PlaybackInfo
   */
  preparePlayback();
  /**
   * 启动播放,可以指定相对开始时间和速率
   * @param { number } start The difference relative to the absolute start time
   * @param { number } rate The multiplier relative to the original rate
   */
  startPlayback(start: number, rate: number);
  /**
   * 启动播放,可以指定相对开始时间和速率
   * @param { number } rate The multiplier relative to the original rate
   */
  restartPlayback(rate?: number);
  /**
   * 改变相对开始时间,一般发生在用户托动进度条
   * @param start The difference relative to the absolute start time
   */
  goToPlayback(start: number): void;
  /**
   * 暂停回放
   */
  pausePlayback(): void;
  /**
   * 设置播放速率
   * @param {number} rate 播放速率
   */
  setRate(rate: number);
  /**
   * 激活playground
   */
  activePlayground(): void;
  /**
   * 运行 playground 方法
   */
  runPlayground(): void;
  /**
   * 停止 playground 方法
   */
  stopPlayground(): void;
  /**
   * 挂载SDK内部组件
   * @param {Component[]} components 组件配置信息
   */
  mapRender(components: Component[]): void;
  /**
   * 卸载已通过 mapRender 挂载的组件。
   * 宿主组件 v-if 切换或父级路由切换时调用，避免下一次 mapRender 撞到守卫。
   * @param {string} componentName 组件名（与 mapRender 的 item 字段对应）
   * @returns {boolean} 之前是否真的挂载过该组件
   */
  unmapRender(componentName: string): boolean;
  /**
   * 设置本地logger打印是否开启的方法
   * @param {any} data 设置的值，当这个值存在就会打印logger
   */
  loggerEnable(data: any): void;
  /**
   * 切换主题
   * @param {ThemeType} type 主题类型
   */
  loadTheme(type: ThemeType): void;
  /**
   * 打开内部指定文件
   * @param filePath
   */
  openFile(filePath: string): Promise<ResultType>;
  /**
   * 更新全局配置
   * @param globalConfig 全局配置
   */
  updateGlobalConfig(globalConfig: GlobalConfig);
  /**
   * 更新配置
   * @param config 配置
   */
  updateConfig(config: Config);
  /**
   * 重新加载
   *
   * 默认参数 ['Editor', 'Tree']
   * @param {ModuleType[]} components 需要刷新的组件
   * @memberof IDaoPaaS
   */
  reload(components: ModuleType[] = ['Editor', 'Tree']): void;
  /**
   * 切换国际化语言
   * @param {I18nLanguageType} language 语言
   */
  switchI18nLanguage(language: I18nLanguageType): void;
  /**
   * 切换国际化语言
   * @param {Array<I18nResourcesType> | I18nLanguageType} lngOrSource -语言类型或者整体资源数组文件
   * @param {any} resource 国际化文本资源（只有lngOrSource为语言类型需要传入）  兼容旧写法
   *
   * 用法:
   * https://snyk.io/advisor/npm-package/i18next/functions/i18next.addResources
   */
  reloadI18nResources(
    lngOrSource: Array<I18nResourcesType> | I18nLanguageType,
    resource?: any,
  ): void;
  /**
   * 设置文件样式
   * @param {FileStyleType} params 参数 - paths文件路径/styles为对应class
   *
   * PS:
   * paths文件路径支持minimatch所支持的模糊路径
   */
  setFileStyle(params: FileStyleType): void;

  /**
   * 切换LSP诊断
   *
   * @param {boolean} openDiagnostic 是否开启诊断报错
   * @memberof IDaoPaaS
   */
  switchLspDiagnostic(openDiagnostic: boolean): void;

  /**
   * 自定义执行，通过业务方携带的配置信息来启动运行
   * tips：而不是通过后端读取配置文件信息
   */
  customExecute(config: ICustomExcuteConfig): void;

  /**
   * 根据光标位置插入内容
   * tips: 该方法可以用于自定义光标定位
   */
  insertCodeByCursor(callback: IInsertCodeExternalFn);
}
