/// <reference types="node" />
/// <reference types="node" />
import { RequestInit } from "node-fetch";
import TypedEmitter from "typed-emitter";
import { Hash } from "crypto";
/**
 * Represents emit event for {@link DownloadProgress}
 */
type DownloadProgressTypeEmitter = {
    error: (error: Error) => void;
    finish: (info: DownloadInfo) => void;
    progress: (chunk: Buffer) => void;
};
declare const DownloadProgress_base: new () => TypedEmitter<DownloadProgressTypeEmitter>;
/**
 * Represents a download progress for file.
 */
export declare class DownloadProgress extends DownloadProgress_base {
    bytesTransferred: number;
    size: number;
    constructor(size?: number);
    /**
     * Updates the counter that is counting a bytes.
     *
     * @param numOfBytes a number of bytes that already transferred
     */
    transferBytes(numOfBytes: number): void;
}
/**
 * Represents a pre-download information.
 */
export interface DownloadInfo {
    /**
     * The url of the file to request HTTP Get method
     */
    url: URL;
    /**
     * The destination of the file to save into
     */
    destination: string;
}
/**
 * Represents an option for a {@link DownloadProcess} class.
 */
export interface DownloadProcessOptions {
    /**
     * The progress of downloading task, see {@link DownloadProgress}
     */
    progress?: DownloadProgress;
    /**
     * The hash observation class to observe the downloading task
     * and return the hash (checksum) of downloading file.
     */
    hashObservation?: DownloadHashObservation;
}
/**
 * Represents a download process.
 * For instance, in order to download a file from url
 * and store it onto destination file
 *
 * ```js
 * import { download } from 'kratos-core'
 * const process = new download.DownloadProcess({
 *  destination: 'path/to/download',
 *  url: new Url('https://example.com')
 * })
 *
 * const processInfo = await process.startDownload();
 * ```
 *
 * In order to observe the download progress,
 * use {@link DownloadProgress}. {@link DownloadProgressTypeEmitter}
 *
 * ```js
 * const progress = new DownloadProgress();
 * const process = new DownloadProcess(
 *  destination: 'path/to/download',
 *  url: new Url('https://example.com')
 * });
 *
 * await process.startDownload();
 *
 * progress.on("progress", (chunk: Buffer) => {  })
 * progress.on("error", (error: Error) => {  })
 * ```
 */
export declare class DownloadProcess {
    private info;
    private options;
    /**
     *
     * @param info the download information such as url, and destination
     * @param options an options for download
     */
    constructor(info: DownloadInfo, options?: DownloadProcessOptions);
    /**
     * Start to download a current download process information.
     *
     * @param init a request initial configuration for node-fetch
     * @returns a current info request
     */
    startDownload(init?: RequestInit): Promise<DownloadInfo>;
    /**
     * Retrieves the local download options.
     *
     * @returns the download options from parameter
     */
    getOptions(): DownloadProcessOptions | undefined;
}
/**
 * Creates a {@link DownloadProcess} for short-hand function
 * instead of using new keywords.
 *
 * @param info {@link DownloadInfo} a download information
 * @param options {@link DownloadProcessOptions} a download options interface
 * @returns a new instance of download process
 */
export declare function createDownloadProcess(info: DownloadInfo, options?: DownloadProcessOptions): DownloadProcess;
/**
 * Represents an observation, consume download data
 * when passing through {@link DownloadProcess} options.
 *
 * For instance, to generate the summation of the file after
 * downloading the file:
 *
 * ```
 * const hashObservation = new download.DownloadHashObservation("sha1");
 * const process = new download.DownloadProcess(downloadInfo, {
 *  hashObservation,
 * });
 *
 * await process.startDownload();
 *
 * const digestedHash = hashObservation.digest();
 * if (digestedHash === 'hash-to-compare') {
 *    // success to compare the file summation
 * } else {
 *    // failed to compare the file summation
 * }
 * ```
 *
 * Be aware of using a large file when downloading, it might cause memory issues.
 *
 * In order to hash a downloadable content, do as follows:
 *
 * ```
 * import {readFileSync} from 'fs';
 *
 * // Start downloading a file
 * const process = new download.DownloadProcess(downloadInfo);
 * await process.startDownload();
 *
 * const filePathDestination = downloadInfo.destination;
 * const hashObservation = new DownloadHashObservation();
 *
 * const fileBuffer =  readFileSync(filePathDestination)
 * hashObservation.update(fileBuffer);
 *
 * const digestedHash = hashObservation.digest();
 * if (digestedHash === 'hash-to-compare') {
 *    // success to compare the file summation
 * } else {
 *    // failed to compare the file summation
 * }
 * ```
 */
export declare class DownloadHashObservation {
    private hash;
    /**
     * The `algorithm` is dependent on the available
     * algorithms supported by the version
     * of OpenSSL on the platform.
     * Examples are `'sha256'`, `'sha512'`, etc.
     * On recent releases of OpenSSL, `openssl list -digest-algorithms`
     *  will display the available digest algorithms.
     *
     * @param algorithm the algorithm of hash function
     */
    constructor(algorithm: string);
    /**
     * Updates data into hash variable.
     *
     * @param buffer the buffer to update the hash variable
     */
    update(buffer: Buffer): void;
    /**
     * Retrieves the digested hash as buffer.
     *
     * @returns the digested hash as a buffer
     */
    digest(): Buffer;
    /**
     * Retrieves the stored hash variables.
     *
     * @returns the variable hash that store updated hash
     */
    getHash(): Hash;
}
/**
 * Represents a emitter for {@link DownloadMatchingProcess}
 */
type DownloadMatchingEmitter = {
    /**
     * Emits when the checksum of the file is not matching with provided hash.
     *
     *
     * @param info the information of the current downloading process
     * @param attempt the number of attempt
     * @param process the current process
     * @returns a void function
     */
    retry: (info: DownloadInfo, attempt: number, process: DownloadMatchingProcess) => void;
    /**
     * Emits when the process is reached to maximum attempt and the hash is invalid.
     *
     * @param process the current process that emitter is running on
     * @returns a void function
     */
    corrupted: (info: DownloadInfo, process: DownloadMatchingProcess) => void;
    /**
     * Emits when the process is complete stream the file.
     *
     * @param info download information of the current process
     * @param process the current process that emitter is running on
     * @returns a void function
     */
    success: (info: DownloadInfo, process: DownloadMatchingProcess) => void;
};
declare const DownloadMatchingObserver_base: new () => TypedEmitter<DownloadMatchingEmitter>;
/**
 * Represents an observer for {@link DownloadMatchingProcess} object.
 */
export declare class DownloadMatchingObserver extends DownloadMatchingObserver_base {
}
/**
 * Represents an option for {@link DownloadMatchingProcess}.
 */
export interface DownloadMatchingOptions {
    /**
     * The hash algorithm to make a hash.
     * The hash is making using {@link DownloadHashObservation}.
     *
     */
    algorithm?: string;
    /**
     * The number of attempt before reject the download file.
     */
    maxAttempt?: number;
    /**
     * The download progress to follow progress of the process.
     */
    progress?: DownloadProgress;
    /**
     * The observer (event listener) to listen to the event from {@link DownloadMatchingProcess}.
     */
    observer?: DownloadMatchingObserver;
}
/**
 * Represents a download process using checksum function to check the integrity of the file
 * before save it.
 *
 * ```js
 *  const mismatchingProcess = new download.DownloadMatchingProcess(
        {
          destination: 'some/path/to/file.f',
          url: new Url("https://google.com/")
        },
        "this-is-a-provided-sha-to-check",
        {
          algorithm: "sha1",
          maxAttempt: 3,
        }
      );
 *

    // Using then
    mismatchingProcess
      .startDownload()
      .then((downloadInfo) => {
        console.log(downloadInfo.destination); // output: some/path/to/file.f
      })

    // Using async/await
    (await mismatchingProcess.startDownload()).destination; // output: some/path/to/file.f
 * ```
 *
 */
export declare class DownloadMatchingProcess {
    private readonly info;
    private readonly hashValue;
    private readonly options;
    private stack;
    private attempt;
    constructor(info: DownloadInfo, hashValue: string, options?: DownloadMatchingOptions);
    private createSubprocess;
    /**
     * Starts downloading the current pending process.
     *
     * @returns the downloaded file information
     */
    startDownload(init?: RequestInit): Promise<DownloadInfo>;
    getDownloadInfo(): DownloadInfo;
}
/**
 * Represents an abbreviation for create a new instance of {@link DownloadMatchingProcess}.
 *
 *
 * @param info the download info.
 * @param hashValue the hash value to check after the file is downloaded.
 * @param options a download options.
 * @returns a new instance of {@link DownloadMatchingProcess}.
 */
export declare function createAttemptDownload(info: DownloadInfo, hashValue: string, options?: DownloadMatchingOptions): DownloadMatchingProcess;
export {};
