import { ReadableStream } from 'stream/web';
import { z } from 'zod';

/**
 * Give the associated URL Address for a Storage Region.
 *
 * @throws: If the value is not a proper storage region.
 */
export declare function addr(value: StorageRegion): URL;

/**
 * Give the associated URL Address for a [StorageZone].
 *
 * @throws If the value is not a proper [StorageRegion].
 */
export declare function addr_alias_1(value: StorageZone): URL;

/**
 * Connect to an associated [StorageZone]
 *
 * ## Examples
 *
 * ### Listing files
 *
 * ```typescript
 *   import * as process from "node:process";
 *   import * as BunnyStorageSDK from "@bunny.net/storage-sdk";
 *
 *   let sz_zone = process.env.STORAGE_ZONE;
 *   let access_key = process.env.STORAGE_ACCESS_KEY;
 *
 *   let region = BunnyStorageSDK.regions.StorageRegion.Falkenstein;
 *   let sz = BunnyStorageSDK.zone.connect_with_accesskey(region, sz_zone, access_key);
 *
 *   let list: BunnyStorageSDK.file.StorageFile[] = await BunnyStorageSDK.file.list(sz, "/");
 * ```
 *
 *
 */
export declare function connect_with_accesskey(region: regions.StorageRegion, name: string, accessKey: string): StorageZone;

/**
 * Create a new Directory in the [StorageZone].
 *
 * @throws
 */
export declare function createDirectory(storageZone: zone.StorageZone, path: string): Promise<boolean>;

/**
 * Download a Stream to a [StorageZone].
 *
 * @throws
 */
export declare function download(storageZone: zone.StorageZone, path: string): Promise<{
    stream: ReadableStream<Uint8Array>;
    response: Response;
    length?: number;
}>;

declare namespace file {
    export {
        get,
        list,
        remove,
        createDirectory,
        removeDirectory,
        upload,
        download,
        ZoneSchema,
        Zone,
        StorageFile,
        UploadOptions
    }
}
export { file }

/**
 * Fetch the metadata of a file from a [StorageZone], to have the data of this
 * file, you'll need to download it.
 *
 * You can download the content of a [StorageFile] by awaitng the `data()`
 * function of this file.
 *
 * @throws
 *
 * ## Example
 *
 * ```typescript
 *   import * as process from "node:process";
 *   import * as BunnyStorageSDK from "@bunny.net/storage-sdk";
 *
 *   let sz_zone = process.env.STORAGE_ZONE;
 *   let access_key = process.env.STORAGE_ACCESS_KEY;
 *
 *   let region = BunnyStorageSDK.regions.StorageRegion.Falkenstein;
 *   let sz = BunnyStorageSDK.zone.connect_with_accesskey(region, sz_zone, access_key);
 *
 *   let file: BunnyStorageSDK.file.StorageFile = await BunnyStorageSDK.file.get(sz, "/somefile");
 *   // Here the body will be in the `stream` file, you can collect it in whatever
 *   // way you need.
 *   // The response will contain the rest of the metadata available.
 *   let promise_to_fetch_the_file: { stream: ReadableStream<Uint8Array>; response: Response; length?: number; } = await file.data();
 * ```
 */
export declare function get(storageZone: zone.StorageZone, path: string): Promise<StorageFile>;

/**
 * Give the associated Authentification header with it's content.
 */
export declare function key(value: StorageZone): [string, string];

/**
 * List files and folders in a directory from a [StorageZone].
 *
 * @throws
 */
export declare function list(storageZone: zone.StorageZone, path: string): Promise<StorageFile[]>;

/**
 * Give the associated Name for a [StorageZone].
 *
 * @throws If the value is not a proper [StorageRegion].
 */
export declare function name(value: StorageZone): string;

declare namespace regions {
    export {
        addr,
        StorageRegion
    }
}
export { regions }

/**
 * Remove files and folders in a directory from a [StorageZone].
 *
 * @throws
 */
export declare function remove(storageZone: zone.StorageZone, path: string): Promise<boolean>;

/**
 * Remove recursively a Directory in the [StorageZone].
 *
 * @throws
 */
export declare function removeDirectory(storageZone: zone.StorageZone, path: string): Promise<boolean>;

export declare const ReplicatedZonesSchema: z.ZodEffects<z.ZodString, ("SE" | "CZ" | "UK" | "ES" | "NY" | "WA" | "MI" | "LA" | "JH" | "HK" | "BR" | "SG" | "JP" | "SYD")[], string>;

export declare const ReplicatedZonesStringSchema: z.ZodString;

/**
 * A [StorageFile] stored in a Storage Zone.
 *
 * Can be a Folder (fake folder)
 */
export declare type StorageFile = {
    readonly _tag: "StorageFile";
    /**
     * The unique GUID of the file.
     */
    guid: string;
    /**
     * The associated ID of the User that holds the file.
     */
    userId: string;
    /**
     * The date when the file was last modified with a ISO 8601 Date.
     */
    lastChanged: Date;
    /**
     * The date when the file was created.
     */
    dateCreated: Date;
    /**
     * The name of the storage zone to which the file is linked.
     */
    storageZoneName: string;
    /**
     * The path to the object
     */
    path: string;
    /**
     * The object name
     */
    objectName: string;
    /**
     * The total length in bytes.
     */
    length: number;
    /**
     * The storage zone internal ID
     */
    storageZoneId: number;
    /**
     * If this is a directory or a file
     */
    isDirectory: boolean;
    /**
     * The server internal ID where the file is stored in your current resolution.
     */
    serverId: number;
    /**
     * The associated checksum of the file you want.
     */
    checksum: string | null;
    /**
     * The zone where the file is actually replicated.
     */
    replicatedZones: Zone[] | null;
    /**
     * The associated content-type of the file.
     */
    contentType: string;
    /**
     * Calling this function will fire a Promise that you'll be able to await to
     * have the stream which will fetch the content of the body of the file you
     * want.
     */
    data: () => Promise<{
        stream: ReadableStream<Uint8Array>;
        response: Response;
        length?: number;
    }>;
};

export declare const StorageFileListing: z.ZodArray<z.ZodObject<{
    Guid: z.ZodString;
    UserId: z.ZodString;
    LastChanged: z.ZodDate;
    DateCreated: z.ZodDate;
    StorageZoneName: z.ZodString;
    Path: z.ZodString;
    ObjectName: z.ZodString;
    Length: z.ZodNumber;
    StorageZoneId: z.ZodNumber;
    IsDirectory: z.ZodBoolean;
    ServerId: z.ZodNumber;
    Checksum: z.ZodNullable<z.ZodString>;
    ReplicatedZones: z.ZodNullable<z.ZodEffects<z.ZodString, ("SE" | "CZ" | "UK" | "ES" | "NY" | "WA" | "MI" | "LA" | "JH" | "HK" | "BR" | "SG" | "JP" | "SYD")[], string>>;
    ContentType: z.ZodString;
}, "strip", z.ZodTypeAny, {
    Guid: string;
    UserId: string;
    LastChanged: Date;
    DateCreated: Date;
    StorageZoneName: string;
    Path: string;
    ObjectName: string;
    Length: number;
    StorageZoneId: number;
    IsDirectory: boolean;
    ServerId: number;
    Checksum: string | null;
    ReplicatedZones: ("SE" | "CZ" | "UK" | "ES" | "NY" | "WA" | "MI" | "LA" | "JH" | "HK" | "BR" | "SG" | "JP" | "SYD")[] | null;
    ContentType: string;
}, {
    Guid: string;
    UserId: string;
    LastChanged: Date;
    DateCreated: Date;
    StorageZoneName: string;
    Path: string;
    ObjectName: string;
    Length: number;
    StorageZoneId: number;
    IsDirectory: boolean;
    ServerId: number;
    Checksum: string | null;
    ReplicatedZones: string | null;
    ContentType: string;
}>, "many">;

export declare const StorageFileSchemaDescribe: z.ZodObject<{
    Guid: z.ZodString;
    UserId: z.ZodString;
    LastChanged: z.ZodDate;
    DateCreated: z.ZodDate;
    StorageZoneName: z.ZodString;
    Path: z.ZodString;
    ObjectName: z.ZodString;
    Length: z.ZodNumber;
    StorageZoneId: z.ZodNumber;
    IsDirectory: z.ZodBoolean;
    ServerId: z.ZodNumber;
    Checksum: z.ZodNullable<z.ZodString>;
    ReplicatedZones: z.ZodNullable<z.ZodEffects<z.ZodString, ("SE" | "CZ" | "UK" | "ES" | "NY" | "WA" | "MI" | "LA" | "JH" | "HK" | "BR" | "SG" | "JP" | "SYD")[], string>>;
    ContentType: z.ZodString;
}, "strip", z.ZodTypeAny, {
    Guid: string;
    UserId: string;
    LastChanged: Date;
    DateCreated: Date;
    StorageZoneName: string;
    Path: string;
    ObjectName: string;
    Length: number;
    StorageZoneId: number;
    IsDirectory: boolean;
    ServerId: number;
    Checksum: string | null;
    ReplicatedZones: ("SE" | "CZ" | "UK" | "ES" | "NY" | "WA" | "MI" | "LA" | "JH" | "HK" | "BR" | "SG" | "JP" | "SYD")[] | null;
    ContentType: string;
}, {
    Guid: string;
    UserId: string;
    LastChanged: Date;
    DateCreated: Date;
    StorageZoneName: string;
    Path: string;
    ObjectName: string;
    Length: number;
    StorageZoneId: number;
    IsDirectory: boolean;
    ServerId: number;
    Checksum: string | null;
    ReplicatedZones: string | null;
    ContentType: string;
}>;

/**
 * Regions available for the primary storage region of your storage Zone
 */
export declare enum StorageRegion {
    Falkenstein = "de",
    London = "uk",
    NewYork = "ny",
    LosAngeles = "la",
    Singapore = "sg",
    Stockholm = "se",
    SaoPaulo = "br",
    Johannesburg = "jh",
    Sydney = "syd"
}

export declare type StorageZone = {
    readonly _tag: "StorageZone";
    region: regions.StorageRegion;
    accessKey: string;
    name: string;
};

/**
 * Upload a Stream to a [StorageZone].
 * Can be used while asynchronously reading a file or reading a network call.
 *
 * @throws
 */
export declare function upload(storageZone: zone.StorageZone, path: string, stream: ReadableStream<Uint8Array>, options?: UploadOptions): Promise<boolean>;

export declare function upload(storageZone: zone.StorageZone, path: string, stream: ReadableStream<Uint8Array>): Promise<boolean>;

export declare type UploadOptions = {
    /**
     * The SHA256 Checksum associated to the data you want to send. If null then
     * the server will automatically calculate it.
     */
    sha256Checksum?: string;
    /**
     * You can override the content-type of the file you upload with this option.
     */
    contentType?: string;
};

export declare type Zone = z.infer<typeof ZoneSchema>;

declare namespace zone {
    export {
        addr_alias_1 as addr,
        name,
        key,
        connect_with_accesskey,
        StorageZone
    }
}
export { zone }

export declare const ZoneSchema: z.ZodUnion<[z.ZodLiteral<"SE">, z.ZodLiteral<"CZ">, z.ZodLiteral<"UK">, z.ZodLiteral<"ES">, z.ZodLiteral<"NY">, z.ZodLiteral<"WA">, z.ZodLiteral<"MI">, z.ZodLiteral<"LA">, z.ZodLiteral<"JH">, z.ZodLiteral<"HK">, z.ZodLiteral<"BR">, z.ZodLiteral<"SG">, z.ZodLiteral<"JP">, z.ZodLiteral<"SYD">]>;

export { }
