import { Ok } from '@hazae41/result';
import { Awaitable } from '../../libs/promises/promises.js';
import { TimedInit, CachedInit, Timed, Cached } from './times.js';

interface DataInit<T> extends TimedInit, CachedInit {
    readonly data: T;
}
declare namespace DataInit {
    type Infer<T> = DataInit<Inner<T>>;
    type Inner<T> = T extends DataInit<infer Inner> ? Inner : never;
}
declare namespace Data {
    type Infer<T> = Data<Inner<T>>;
    type Inner<T> = T extends Data<infer Inner> ? Inner : never;
}
declare class Data<T> extends Ok<T> implements DataInit<T>, Timed, Cached {
    readonly data: T;
    readonly time: number;
    readonly cooldown?: number;
    readonly expiration?: number;
    constructor(data: T, init?: TimedInit & CachedInit);
    static from<T>(init: DataInit<T>): Data<T>;
    isData(): this is Data<T>;
    isFail(): false;
    set<U>(inner: U): Data<U>;
    setErr(inner: unknown): this;
    setInit(init?: TimedInit & CachedInit): Data<T>;
    map<U>(mapper: (data: T) => Awaitable<U>): Promise<Data<U>>;
    mapSync<U>(mapper: (data: T) => U): Data<U>;
    /**
     * Transform Result<Promise<T>, E> into Promise<Result<T, E>>
     * @returns `await this.inner` if `Ok`, `this` if `Err`
     */
    await<T>(this: Data<PromiseLike<T>>): Promise<Data<Awaited<T>>>;
    /**
     * Transform Result<T, Promise<E>> into Promise<Result<T, E>>
     * @returns `await this.inner` if `Err`, `this` if `Ok`
     */
    awaitErr(): Promise<this>;
    /**
     * Transform Result<Promise<T>, Promise<E>> into Promise<Result<T, E>>
     * @returns `await this.inner`
     */
    awaitAll<T>(this: Data<PromiseLike<T>>): Promise<Data<Awaited<T>>>;
}

export { Data, DataInit };
