import type { UUID } from 'node:crypto';
import type { ConstMap } from 'utilium';
import type { InodeLike } from './inode.js';
/**
 * Usage information about a file system
 * @category Internals
 * @internal
 */
export interface UsageInfo {
    /**
     * The total space
     */
    totalSpace: number;
    /**
     * The available space
     */
    freeSpace: number;
    /**
     * The optimal block size to use with the file system
     * @default 4096
     */
    blockSize?: number;
    /**
     * Total number of nodes available
     */
    totalNodes?: number;
    /**
     * Number of free nodes available
     */
    freeNodes?: number;
}
export type CaseFold = 'upper' | 'lower';
/**
 * Attributes that control how the file system interacts with the VFS.
 * No options are set by default.
 * @category Internals
 * @internal
 */
export interface FileSystemAttributes {
    /**
     * If set disables async file systems from preloading their contents.
     * This means *sync operations will not work* (unless the contents are cached)
     * It has no affect on sync file systems.
     */
    no_async_preload: void;
    /**
     * Currently unused. In the future, this will disable caching.
     * Analogous to `S_DAX` on every file.
     */
    no_cache: void;
    /**
     * If set, the file system should not be written to.
     * This should be set for read-only file systems.
     * Note this does NOT trigger EROFS errors;
     * writes will silently be dropped.
     */
    no_write: void;
    /**
     * The FS is using the default implementation for `streamRead`
     * @internal
     */
    default_stream_read: void;
    /**
     * The FS is using the default implementation for `streamWrite`
     * @internal
     */
    default_stream_write: void;
    /**
     * Do not update access times.
     */
    no_atime: void;
    /**
     * Ignore suid and sgid bits.
     * @todo Implement
     * @experimental
     */
    no_suid: void;
    /**
     * Writes are synced at once
     * @experimental
     */
    sync: void;
    /**
     * If set, the VFS layer will convert paths to lower/upper case.
     */
    case_fold?: CaseFold;
}
/**
 * Options used when creating files and directories.
 * This weird naming and such is to preserve backward compatibility.
 * @category Internals
 * @internal
 */
export interface CreationOptions extends Partial<InodeLike> {
    /**
     * The uid to create the file.
     * This is ignored if the FS supports setuid and the setuid bit is set
     */
    uid: number;
    /**
     * The gid to create the file.
     * This is ignored if the FS supports setgid and the setgid bit is set
     */
    gid: number;
    /**
     * The mode to create the file with.
     */
    mode: number;
}
/**
 * Options for streaming operations
 * @category Internals
 * @internal
 */
export interface StreamOptions {
    start?: number;
    end?: number;
    autoClose?: boolean;
}
/**
 * Provides a consistent and easy to use internal API.
 * Default implementations for `exists` and `existsSync` are included.
 * If you are extending this class, note that every path is an absolute path and all arguments are present.
 * @category Internals
 * @internal
 */
export declare abstract class FileSystem {
    /**
     * A unique ID for this kind of file system.
     * Currently unused internally, but could be used for partition tables or something
     */
    readonly type: number;
    /**
     * The name for this file system.
     * For example, tmpfs for an in memory one
     */
    readonly name: string;
    label?: string;
    /**
     * The last place this file system was mounted
     * @internal @protected
     */
    _mountPoint?: string;
    /**
     * The UUID of the file system.
     * @privateRemarks This is only used by `ioctl`
     * @internal @protected
     */
    _uuid: UUID;
    get uuid(): UUID;
    /**
     * @see FileSystemAttributes
     */
    readonly attributes: ConstMap<FileSystemAttributes> & Map<string, any>;
    constructor(
    /**
     * A unique ID for this kind of file system.
     * Currently unused internally, but could be used for partition tables or something
     */
    type: number, 
    /**
     * The name for this file system.
     * For example, tmpfs for an in memory one
     */
    name: string);
    toString(): string;
    /**
     * Default implementation.
     * @todo Implement
     * @experimental
     */
    usage(): UsageInfo;
    ready(): Promise<void>;
    readySync(): void;
    abstract rename(oldPath: string, newPath: string): Promise<void>;
    abstract renameSync(oldPath: string, newPath: string): void;
    abstract stat(path: string): Promise<InodeLike>;
    abstract statSync(path: string): InodeLike;
    /** Modify metadata. */
    abstract touch(path: string, metadata: Partial<InodeLike>): Promise<void>;
    /** Modify metadata. */
    abstract touchSync(path: string, metadata: Partial<InodeLike>): void;
    /**
     * Create the file at `path` with the given options.
     */
    abstract createFile(path: string, options: CreationOptions): Promise<InodeLike>;
    /**
     * Create the file at `path` with the given options.
     */
    abstract createFileSync(path: string, options: CreationOptions): InodeLike;
    abstract unlink(path: string): Promise<void>;
    abstract unlinkSync(path: string): void;
    abstract rmdir(path: string): Promise<void>;
    abstract rmdirSync(path: string): void;
    abstract mkdir(path: string, options: CreationOptions): Promise<InodeLike>;
    abstract mkdirSync(path: string, options: CreationOptions): InodeLike;
    abstract readdir(path: string): Promise<string[]>;
    abstract readdirSync(path: string): string[];
    /**
     * Test whether or not `path` exists.
     */
    exists(path: string): Promise<boolean>;
    /**
     * Test whether or not `path` exists.
     */
    existsSync(path: string): boolean;
    abstract link(target: string, link: string): Promise<void>;
    abstract linkSync(target: string, link: string): void;
    abstract sync(): Promise<void>;
    abstract syncSync(): void;
    /**
     * Reads into a buffer
     * @param buffer The buffer to read into. You must set the `byteOffset` and `byteLength` appropriately!
     * @param start The offset into the file to start reading from
     * @param end The position in the file to stop reading
     */
    abstract read(path: string, buffer: Uint8Array, start: number, end: number): Promise<void>;
    /**
     * Reads into a buffer
     * @param buffer The buffer to read into. You must set the `byteOffset` and `byteLength` appropriately!
     * @param start The offset into the file to start reading from
     * @param end The position in the file to stop reading
     */
    abstract readSync(path: string, buffer: Uint8Array, start: number, end: number): void;
    /**
     * Writes a buffer to a file
     * @param buffer The buffer to write. You must set the `byteOffset` and `byteLength` appropriately!
     * @param offset The offset in the file to start writing
     */
    abstract write(path: string, buffer: Uint8Array, offset: number): Promise<void>;
    /**
     * Writes a buffer to a file
     * @param buffer The buffer to write. You must set the `byteOffset` and `byteLength` appropriately!
     * @param offset The offset in the file to start writing
     */
    abstract writeSync(path: string, buffer: Uint8Array, offset: number): void;
    /**
     * Read a file using a stream.
     * @privateRemarks The default implementation of `streamRead` uses "chunked" `read`s
     */
    streamRead(path: string, options: StreamOptions): ReadableStream;
    /**
     * Write a file using stream.
     * @privateRemarks The default implementation of `streamWrite` uses "chunked" `write`s
     */
    streamWrite(path: string, options: StreamOptions): WritableStream;
}
