/**
 * 识别解析
 *
 * @remarks
 * 这是一个 `识别—解析` 工具，用户可以注册识别器 和 解析器，对于输入资源，它会先用用注册的识别器进行识别，识别出类型之后，再调用用户注册的对应类型的解析器进行解析，这是它的基本机制，同时它具备一些更具通用性、扩展性、复用性 和 易用性 的机制，比如：支持前置识别器、后置识别器、前置解析器、后置解析器、一进多出、异步识别、异步解析 等等。
 *
 * @packageDocumentation
 */

import { Parse as Parse_2 } from './Resolver';

/**
 * 格式化后的鉴别结果
 *
 * @remarks
 * 没有鉴定出来的 返回  null
 * 识别出来的，返回 {@link JudgeInfo} 类型的数组，且至少有一个元素
 */
export declare type FormatJudgeResult = JudgeInfo[] | null;

/**
 * 鉴定函数
 * @remarks
 * 鉴定 target 的类型 和 格式化数据，如果返回 空，表示鉴定失败
 *
 * @param target - 目标
 * @param targetOptions - 目标相关的选项
 * @param preResult - 上一个鉴定函数的鉴定结果
 * @returns 返回鉴定结果，可以是异步的鉴定结果；鉴定结果是可以是 一个 或 一组 鉴定信息 {@link JudgeInfo}，也可以是空，如果是空 表示鉴定失败
 */
export declare type Judge<Options = any> = (target: any, targetOptions: Options, preResult: FormatJudgeResult) => JudgeReturn;

/**
 * 鉴定信息
 */
export declare interface JudgeInfo {
    /**
     * 鉴定出来的类型
     */
    type: string;
    /**
     * 内容数据
     */
    content?: any;
}

/**
 * 鉴定者
 *
 * @remarks
 * 表示可以用作为一次独立鉴定的鉴定者。如果最终返回值为空，则表示鉴定失败；如果最终返回的有鉴定信息 {@link JudgeInfo}，则表示鉴定成功
 */
export declare type Judger<Options = any> = SerialJudger<Options> | Judge<Options>;

/**
 * 鉴定结果
 *
 * @remarks
 * 表示鉴定的最终结果，空值 表示鉴定失败，非空的值 表示鉴定出来的鉴定信息，可以是多个鉴定信息
 */
export declare type JudgeResult = JudgeInfo[] | JudgeInfo | null | undefined;

/**
 * 监定函数的返回值的类型
 * @remarks
 * 可以是同步的结果 {@link JudgeResult} 也可以是异步的 `Promise<JudgeResult>`
 */
export declare type JudgeReturn = Promise<JudgeResult> | JudgeResult;

/**
 * 命名的监定者集合
 * @remarks
 * 名字 与 串行鉴定者 的映射
 */
export declare interface NamedJudgers<Options = any> {
    /**
     * key 是名字，value 是串行鉴定者
     */
    [name: string]: Judger<Options>;
}

/**
 * 命名的串行监定者集合
 * @remarks
 * 名字 与 串行鉴定者 的映射
 */
export declare interface NamedSerialJudgers<Options = any> {
    /**
     * key 是名字，value 是串行鉴定者
     */
    [name: string]: SerialJudger<Options>;
}

/**
 * 解析函数
 * @remarks
 * 对 target 进行解析
 *
 * @param target - 目标
 * @param targetOptions - 目标相关的选项
 * @param preResult - 之前的解析结果
 * @param recognResult - 识别结果
 * @returns 解析的结果
 */
export declare type Parse<Options = any> = (target: any, targetOptions: Options, preResult: any, recognResult: JudgeInfo) => any;

/**
 * 识别解析出的信息
 */
export declare interface ParseInfo {
    /**
     * 识别出的信息
     */
    recogn: JudgeInfo;
    /**
     * 解析出的信息
     */
    parse: any;
}

/**
 * 解析器
 * @remarks
 * 解析器可以是一个解析函数，也可以是一组解析函数。
 * 当是一组解析函数时，所有的解析函数都会依次执行。并会以最后一个解析函数返回的结果为最终的解析结果。
 */
export declare type Parser<Options = any> = SerialParser<Options> | Parse<Options>;

/**
 * 识别器
 *
 * @remarks
 * 负责识别操作，所有的识别逻辑都是由该类来完成的。
 *
 * 每次执行识别操作时，会按照如下顺序调用鉴定者：
 *
 * 1. 依次执行前置鉴定者列表 `preJudgers` 中的鉴定者，如果有鉴定成功的，则会停止后续的前置鉴定者的执行，并将鉴定结果 传给后续流程。
 *
 * 2. 如果提供了 name，则会在 命名的鉴定者 中查找 name 对应的鉴定者，然后执行指定的鉴定者。然后 跳到 步骤 5。
 *
 * 3. 如果没有提供 name，则会执行 匿名的鉴定者列表。如果有鉴定结果，则会 跳到 步骤 5。
 *
 * 4. 否则，则会执行 所有的命名鉴定者。如果有鉴定结果，则会 跳到 步骤 5。
 *
 * 5. 依次执行后置鉴定者列表 `postJudgers` 中的鉴定者，如果有鉴定成功的，则会停止后续的后置鉴定者的执行，并返回 鉴定结果。否则返回 空；
 */
export declare class Recognizer<Options = any> {
    /**
     * 前置鉴定者
     */
    get preJudgers(): Judger<Options>[];
    set preJudgers(value: Judger<Options>[]);
    /**
     * @internal
     */
    protected _preJudgers: Judger<Options>[];
    /**
     * 后置鉴定者
     */
    get postJudgers(): Judger<Options>[];
    set postJudgers(value: Judger<Options>[]);
    /**
     * @internal
     */
    protected _postJudgers: Judger<Options>[];
    /**
     * 命名的鉴定者
     * @remarks
     * namedJudgers 中的识别顺序是按照加入 namedJudgers 中时的顺序来识别的
     *
     * namedJudgers {@link Recognizer.namedJudgers} 的优先级低于 judgers {@link Recognizer.judgers}，即：
     * 会先执行 judgers 中的识别器，如果不能识别，再执行 namedJudgers 中的识别器
     */
    readonly namedJudgers: Map<string, SerialJudger<Options>>;
    /**
     * 匿名的鉴定者列表
     *
     * @remarks
     * namedJudgers {@link Recognizer.namedJudgers} 的优先级低于 judgers {@link Recognizer.judgers}，即：
     * 会先执行 judgers 中的识别器，如果不能识别，再执行 namedJudgers 中的识别器
     */
    readonly judgers: Judger<Options>[];
    /**
     * 所有的鉴定者
     */
    get allJudgers(): Judger<Options>[];
    /**
     * 添加鉴定者
     * @param judge - 鉴定者
     * @param name - 鉴定者的名字
     */
    add(judge: Judger<Options>, name?: string | null): void;
    /**
     * 添加多个鉴定者
     * @param judgers - 鉴定者列表 或 名字与鉴定者的映射
     */
    addJudgers(judgers: Judger<Options>[] | NamedJudgers<Options>): void;
    /**
     * 移除指定名字的鉴定者
     * @param name - 鉴定者的名字
     * @returns 返回值表示 是否移除成功
     */
    removeByName(name: string[] | string): boolean;
    /**
     * 删除 指定的 judger
     *
     * @remarks
     * 当 judger 为 数组类型时，会把其作为 SerialJudger 来对象，不会对 SerialJudger 中包含的 各个 Judge 进行单独查找与删除
     *
     * @param judger - 鉴定者
     * @returns 表示是否移除成功
     */
    remove(judger: Judger<Options>): boolean;
    /**
     * 批量删除
     *
     * @remarks
     * 会先按照 {@link Recognizer.remove} 的逻辑进行删除，如果删除不成功，则会把 judges 或 其包含的 所有 Judge 进行单独查找与删除，也会在 SerialJudger 的元素中进行查找与删除
     *
     * @param judges
     * @returns 表示是否成功移除
     */
    removeJudges(judges: Judger<Options>): boolean;
    /**
     * 识别目标
     *
     * @remarks
     * 具体的执行逻辑请看 {@link Recognizer}
     *
     * @param target - 目标
     * @param targetOptions - 目标选项
     * @param name - 鉴定者的名字
     *
     * @return 返回的结果可能是同步的，也可能是异步的
     */
    recogn(target: any, targetOptions?: any, name?: string | null): RecognResult;
    /**
     * 异步识别
     *
     * @remarks
     * 只有当最终有识别结果时，才会 resolve，否则，则会 reject。
     * 具体的执行逻辑请看 {@link Recognizer}
     *
     * @param target - 目标
     * @param targetOptions - 目标选项
     * @param name - 鉴定者的名字
     */
    recognAsync(target: any, targetOptions?: any, name?: string | null): Promise<JudgeInfo[]>;
}

/**
 * 识别解析
 * @remarks
 * 是用户直接操作的主类，提供了完整的 `识别-解析` 机制
 */
export declare class RecognParse<TOptions = any> {
    /**
     * @internal
     */
    protected _recognizer?: Recognizer<TOptions> | null;
    /**
     * 识别器
     */
    get recognizer(): Recognizer<TOptions>;
    set recognizer(value: Recognizer<TOptions>);
    /**
     * 前置鉴定器
     */
    get preJudgers(): Judger<TOptions>[];
    set preJudgers(value: Judger<TOptions>[]);
    /**
     * 后置鉴定器
     */
    get postJudgers(): Judger<TOptions>[];
    set postJudgers(value: Judger<TOptions>[]);
    /**
     * @internal
     */
    protected _resolver?: Resolver<TOptions> | null;
    /**
     * 解决者
     */
    get resolver(): Resolver<TOptions>;
    set resolver(value: Resolver<TOptions>);
    /**
     * 前置解析器
     */
    get preParses(): Parse_2<TOptions>[];
    set preParses(value: Parse_2<TOptions>[]);
    /**
     * 后置解析器
     */
    get postParses(): Parse_2<TOptions>[];
    set postParses(value: Parse_2<TOptions>[]);
    /**
     * 给指定类型添加鉴定解析器
     * @param type - 类型
     * @param judgerParser - 包含鉴定器 和 解析器
     */
    add(type: string, judgerParser: RecognParser<TOptions>): void;
    /**
     * 批量添加鉴定解析器
     * @param recognParsers - 类型 和 鉴定器和解析器对的映射
     */
    addRecognParsers(recognParsers: TypeRecognParsers<TOptions>): void;
    /**
     * 移除指定类型的鉴定器和解析器
     * @param type - 类型
     */
    remove(type: string[] | string): void;
    /**
     * {@inheritDoc ./Recognizer#Recognizer.recogn}
     */
    recogn(target: any, targetOptions?: any, name?: string | null): RecognResult;
    /**
     * {@inheritDoc ./Recognizer#Recognizer.recognAsync}
     */
    recognAsync(target: any, targetOptions?: any, name?: string | null): Promise<JudgeInfo[]>;
    /**
     * 识别并解析 target
     *
     * @param target - 识别解析的目标
     * @param targetOpts - 目标选项，主要包含的是与目标相关的选项，大多数场景可能是服务于解析目标的，往往不同类型的目标会有不同的选项，
     * @param options - resolve 方法本身的选项，用于控制 识别解析过程的，而不是控制针对目标的具体的鉴定、解析逻辑的，通常与目标无关。
     */
    resolve(target: any, targetOpts: TOptions, options?: ResolveOptions | null): RecognParseResult;
    /**
     * 异步识别并解析
     *
     * @remarks
     * 只有当最终有识别结果时，才会 resolve，否则，则会 reject
     *
     * @param target - 识别解析的目标
     * @param targetOpts - 目标选项，主要包含的是与目标相关的选项，大多数场景可能是服务于解析目标的，往往不同类型的目标会有不同的选项，
     * @param options - resolve 方法本身的选项，用于控制 识别解析过程的，而不是控制针对目标的具体的鉴定、解析逻辑的，通常与目标无关。
     */
    resolveAsync(target: any, targetOpts: TOptions, options?: ResolveOptions | null): RecognParseResult_Async;
    /**
     * 解析识别的结果
     * @param judgeResult - 识别的结果
     * @param target - 目标
     * @param targetOptions - 目标选项，主要包含的是与目标相关的选项，大多数场景可能是服务于解析目标的，往往不同类型的目标会有不同的选项，
     */
    parse(judgeResult: FormatJudgeResult, target: any, targetOptions: TOptions): RecognParseInfo | null;
}

/**
 * 识别解析信息的集合
 * @remarks
 * 是 类型 和 识别解析出的信息的映射
 */
export declare interface RecognParseInfo {
    /**
     * key 是类型，value 是识别和解析的信息
     */
    [type: string]: ParseInfo;
}

/**
 * 鉴定器和解析器对
 */
export declare interface RecognParser<Options = any> {
    judger?: Judger<Options> | null;
    parser?: Parser<Options> | null;
}

/**
 * 识别解析的结果
 * @remarks
 * 可以是同步 或 异步的 识别解析信息的集合
 */
export declare type RecognParseResult = RecognParseInfo | null | Promise<RecognParseInfo | null>;

/**
 * 异步识别解析的结果
 */
export declare type RecognParseResult_Async = Promise<RecognParseInfo>;

/**
 * 识别结果
 * @remarks
 * 可以是同步的 格式化后的 {@link FormatJudgeResult} 鉴定结果，也可以是 异步的 `Promise<FormatJudgeResult>`
 */
export declare type RecognResult = Promise<FormatJudgeResult> | FormatJudgeResult;

/**
 * resolve 方法的选项
 */
export declare interface ResolveOptions {
    /**
     * 指定的类型
     */
    type?: string | null;
    /**
     * 指定鉴定器的名字
     */
    recogn?: string | null;
    /**
     * 指定解析的类型
     */
    parse?: string | null;
    /**
     * 跳过识别
     */
    noRecogn?: boolean | null;
}

/**
 * 解决者
 *
 * @remarks
 * 负责解析操作，所有的解析逻辑都是由该类来完成的。
 *
 * 每次执行解决操作时，会按照如下顺序调用解析器：
 *
 * 1. 如果找不到对应类型 type 的 解析器，则会终止解决流程。
 *
 * 2. 依次执行前置解析器 `preParses` 中的所有解析函数，即使有抛出错误，也会继续执行，并会以最后一个解析函数返回的结果为最终前置解析器的解析结果，然后将 前置解析的结果 传给后续的解析器。
 *
 * 3. 依次执行根据 类型 type 查找到的解析器序列。如果序列中任意解析器抛出错误，则会终止解决流程。否则，以最后一个解析函数返回的结果为最终的解析结果 并 传递给后续的解析器。
 *
 * 4. 依次执行后置解析器 `postParses` 中的所有解析函数，即使有抛出错误，也会继续执行，并会以最后一个解析函数返回的结果为最终的解析结果。
 */
export declare class Resolver<Options = any> {
    /**
     * 前置解析器
     * @remarks
     * 详情请看 {@link Resolver}
     */
    get preParses(): Parse<Options>[];
    set preParses(value: Parse<Options>[]);
    /**
     * @internal
     */
    protected _preParses?: Parse<Options>[] | null;
    /**
     * 后置解析器
     * @remarks
     * 详情请看 {@link Resolver}
     */
    get postParses(): Parse<Options>[];
    set postParses(value: Parse<Options>[]);
    /**
     * @internal
     */
    protected _postParses: Parse<Options>[];
    /**
     * 类型与解析器的映射
     */
    get typeParsers(): TypeParsers<any>;
    set typeParsers(value: TypeParsers<any>);
    /**
     * @internal
     */
    protected _typeParsers?: TypeParsers | null;
    /**
     * 添加解析器
     * @param type - 类型
     * @param parser - 解析器
     */
    add(type: string, parser: Parser<Options>): void;
    /**
     * 添加多个解析器
     * @param parsers - 类型 与 解析器的映射集合
     */
    addParsers(parsers: TypeParsersOption<Options>): void;
    /**
     * 删除 解析器
     * @param type - 类型
     * @param parser - 被删除的解析器
     * @returns 是否成功删除
     */
    remove(type: string, parser?: Parser<Options> | null): boolean;
    /**
     * 移除指定类型的解析器
     * @param type - 类型 或 类型列表
     * @returns
     */
    removeType(type: string[] | string): boolean;
    /**
     * 解决
     *
     * @remarks
     * 解决的过程请看 {@link Resolver}
     *
     * @param type - 类型
     * @param target - 目标
     * @param targetOptions - 目标相关的选项
     * @param recognResult - 识别结果
     * @returns
     */
    resolve(type: string, target: any, targetOptions?: any, recognResult?: any): any | Promise<any>;
    /**
     * 异步解决
     *
     * @remarks
     * 只有当最终有识别结果时，才会 resolve，否则，则会 reject。
     * 解决的过程请看 {@link Resolver}
     *
     * @param type - 类型
     * @param target - 目标
     * @param targetOptions - 目标相关的选项
     * @param recognResult - 识别结果
     * @returns
     */
    resolveAsync(type: string, target: any, targetOptions?: any, recognResult?: any): Promise<NonNullable<any>>;
}

/**
 * 串行鉴定者
 *
 * @remarks
 * 串行鉴定者就是一组鉴定函数，所有的鉴定函数都会依次执行，不论中间有没有失败，都会依次执行完所有的鉴定函数，并会以最后一个鉴定函数返回的结果为最终的鉴定结果。
 * 串行鉴定者序列中的任何项识别失败都不会中止 串行鉴定者序列 的执行。
 * 即：即使 串行鉴定者序列 SerialJudger 中的某一个 Judge 返回 null 或者 抛出错误，则仍会执行此 串行鉴定者序列 SerialJudger 中的下一个 Judge
 */
export declare type SerialJudger<Options = any> = Judge<Options>[];

/**
 * 串行解析器
 *
 * @remarks
 * 串行解析器就是一组解析函数，这些解析函数会依次执行，并会以最后一个解析函数返回的结果为最终的解析结果。这组解析函数中如果有解析函数抛出错误，则会终止解决流程。
 */
export declare type SerialParser<Options = any> = Parse<Options>[];

/**
 * 类型与解析器的映射
 */
export declare interface TypeParsers<Options = any> {
    /**
     * key 是类型，value 是串行解析器
     */
    [type: string]: SerialParser;
}

/**
 * 解析器集合
 * @remarks
 * 类型 与 解析器的 映射
 */
export declare interface TypeParsersOption<Options = any> {
    /**
     * key 是类型，value 是解析器
     */
    [type: string]: Parser<Options>;
}

/**
 * 识别解析选项
 */
export declare interface TypeRecognParsers<Options = any> {
    /**
     * key 是类型，value 是 鉴定器和解析器对
     */
    [type: string]: RecognParser<Options>;
}

export { }
