type Bit = 0 | 1;

/**
 * Enum of all valid WebSocket frame opcodes, defined by RFC 6455 §5.2.
 */
declare enum PulseFrameOpcode {
    /** Continuation frame for fragmented messages */
    CONTINUATION = 0,
    /** Text message frame */
    TEXT = 1,
    /** Binary message frame */
    BINARY = 2,
    /** Connection close frame */
    CLOSE = 8,
    /** Ping frame */
    PING = 9,
    /** Pong frame */
    PONG = 10
}

/**
 * Represents a parsed WebSocket frame header.
 * Contains control flags, opcode, payload length, and optional masking information.
 */
type PulseFrameHeader = {
    /** Final frame indicator (FIN bit) */
    fin: Bit;
    /** Reserved bit 1 (RSV1) */
    rsv1: Bit;
    /** Reserved bit 2 (RSV2) */
    rsv2: Bit;
    /** Reserved bit 3 (RSV3) */
    rsv3: Bit;
    /** Indicates whether the payload is masked (MASK bit) */
    mask: Bit;
    /** The opcode defining the frame type (e.g., text, binary, ping) */
    opcode: PulseFrameOpcode;
    /** Payload length (7-bit base or extended if necessary) */
    length: number;
    /** Length of the extension data prefix, if any */
    extensionDataLength: number;
    /** The 4-byte masking key, present only if `mask` is 1 */
    maskingKey?: Buffer;
};

/**
 * Represents a single WebSocket frame, parsed or constructed manually.
 *
 * A frame is the fundamental unit of data transmission in the WebSocket protocol.
 *
 * @see [RFC 6455, Section 5.2 - Base Framing Protocol](https://www.rfc-editor.org/rfc/rfc6455#section-5.2)
 */
declare class PulseFrame {
    private readonly header;
    private readonly payload;
    private readonly extensionData?;
    private readonly applicationData?;
    private readonly masked;
    constructor(header: PulseFrameHeader, payloadData: Buffer, extensionData?: Buffer, applicationData?: Buffer);
    /**
     * Only used internally after parsing to set application-level decoded payload.
     */
    setApplicationData(data: Buffer): void;
    /**
     * Returns the decoded payload (application data if available).
     */
    getPayload(): Buffer;
    /**
     * Returns the payload as a UTF-8 string, if any.
     */
    getPayloadString(): string;
    /**
     * Returns the parsed extension data.
     */
    getExtensionData(): Buffer | undefined;
    /**
     * Returns the raw parsed header.
     */
    getHeader(): PulseFrameHeader;
    /** Whether the payload was masked. */
    isMasked(): boolean;
    /** Whether this is the final frame in a sequence. */
    isFinal(): boolean;
    /** Returns the frame's opcode. */
    getOpcode(): PulseFrameOpcode;
    /** Whether this frame contains text data. */
    isText(): boolean;
    /** Whether this frame contains binary data. */
    isBinary(): boolean;
    /** Whether this frame continues a fragmented message. */
    isContinuation(): boolean;
    /** Whether this frame is a control frame. */
    isControl(): boolean;
    /** Whether this frame is a ping. */
    isPing(): boolean;
    /** Whether this frame is a pong. */
    isPong(): boolean;
    /** Whether this frame is a connection close. */
    isClose(): boolean;
    /** Whether this is a text or binary data frame. */
    isData(): boolean;
    /**
     * Converts this frame to a plain object for logging or inspection.
     */
    toJSON(): Record<string, unknown>;
    /**
     * Returns a short string representation of the frame.
     */
    toString(): string;
}

/**
 * @spec RFC 6455 §5.2 — Base Framing Protocol
 *
 * Options for constructing a new WebSocket frame in `createFrame`.
 */
type PulseFrameBuildOptions = {
    /**
     * Final fragment bit. Indicates that this is the final frame of a message.
     * @default 1
     */
    fin?: Bit;
    /**
     * Opcode for the frame, defining its type (e.g., TEXT, BINARY, CLOSE, PING).
     */
    opcode: PulseFrameOpcode;
    /**
     * Reserved bit 1. Used for negotiated extensions (e.g., permessage-deflate).
     * @default 0
     */
    rsv1?: Bit;
    /**
     * Reserved bit 2. Used for negotiated extensions.
     * @default 0
     */
    rsv2?: Bit;
    /**
     * Reserved bit 3. Used for negotiated extensions.
     * @default 0
     */
    rsv3?: Bit;
    /**
     * Indicates if the payload should be masked (typically true for client frames).
     * @default 0
     */
    mask?: Bit;
    /**
     * Optional 4-byte masking key if `mask` is set to 1.
     */
    maskingKey?: Buffer;
    /**
     * The raw payload buffer to send (application + extension data).
     */
    payloadData?: Buffer;
    /**
     * The number of bytes in the payload reserved for extensions.
     * @default 0
     */
    extensionDataLength?: number;
    /**
     * Optional extension data buffer, separate from application payload.
     */
    extensionData?: Buffer;
};

/**
 * Creates a complete `PulseFrame` instance for transmission over a WebSocket connection.
 *
 * This function builds the frame header and payload according to
 * [RFC 6455 §5.2 - Base Framing Protocol](https://datatracker.ietf.org/doc/html/rfc6455#section-5.2),
 * ensuring correct encoding of all fields and masking (if required).
 *
 * ### RFC 6455 Compliance:
 *
 * - **FIN / RSV1-3 bits**: Set based on options; used for fragmentation and extensions.
 * - **Opcode**: Determines the type of frame (text, binary, close, ping, pong).
 * - **Masking**:
 *   - Applied if `mask` is `1` and a `maskingKey` is provided.
 *   - Required for clients; servers **MUST NOT** mask frames ([RFC §5.1]).
 * - **Payload length**:
 *   - Calculated after masking is applied.
 *   - Determines how many length bytes will be encoded later in serialization.
 *
 * This function does **not** serialize the frame; it prepares the internal representation.
 * For binary transmission, use `frame.toBuffer()`.
 *
 * @param options - Frame metadata and payload data.
 * @returns A fully prepared {@link PulseFrame} instance with a correct header and (optionally masked) payload.
 *
 * @example
 * ```ts
 * const frame = createFrame({
 *   fin: 1,
 *   opcode: PulseFrameOpcode.TEXT,
 *   mask: 1,
 *   maskingKey: createRandomBytes(4),
 *   payloadData: Buffer.from("Hello"),
 * });
 * socket.write(frame.toBuffer());
 * ```
 *
 * @see RFC 6455 §5.2 - Base Framing Protocol
 * @see RFC 6455 §5.1 - Client-to-Server Masking
 */
declare function createFrame(options: PulseFrameBuildOptions): PulseFrame;

/**
 * Indicates which reserved bits (RSV1, RSV2, RSV3) are supported by negotiated extensions.
 * If a bit is set to true, it means an extension has explicitly enabled it.
 */
type PulseFrameExtensionSupport = {
    rsv1?: boolean;
    rsv2?: boolean;
    rsv3?: boolean;
};

/**
 * Options for parsing or validating a WebSocket frame.
 * These are typically passed during buffer decoding.
 */
type PulseFrameOptions = {
    /** Length of the extension data to strip from the start of the payload */
    extensionLength?: number;
    /** Negotiated extension bit support (RSV1/RSV2/RSV3) */
    extensionSupport: PulseFrameExtensionSupport;
};

/**
 * Parses a WebSocket frame from a raw buffer according to [RFC 6455 §5](https://datatracker.ietf.org/doc/html/rfc6455#section-5).
 *
 * This function:
 * - Validates header size and structure
 * - Extracts masking key, extended payload length, and payload data
 * - Validates RSV bits, opcodes, and control frame rules
 * - Unmasks payload if required
 * - Separates extension data from application data
 *
 * Supports optional extension handling via {@link PulseFrameOptions}.
 *
 * @param buffer - The raw incoming buffer containing a WebSocket frame.
 * @param options - Optional framing behavior configuration, including extension support and extension data length.
 * @returns A parsed and validated {@link PulseFrame} object.
 *
 * @throws {PulseFrameError} If the frame is incomplete, invalid, or violates protocol constraints.
 *
 * @example
 * ```ts
 * const frame = createFrameFromBuffer(buffer, {
 *   extensionLength: 8,
 *   extensionSupport: { rsv1: true }
 * });
 * ```
 *
 * @see RFC 6455 §5 - Data Framing
 * @see RFC 6455 §5.5 - Control Frames
 * @see RFC 6455 §7 - Closing Handshake
 */
declare function createFrameFromBuffer(buffer: Buffer, options?: PulseFrameOptions): PulseFrame;

/**
 * Creates a WebSocket control frame according to [RFC 6455 §5.5](https://datatracker.ietf.org/doc/html/rfc6455#section-5.5).
 *
 * This utility is used to generate Ping, Pong, and Close frames with the correct header flags:
 * - FIN bit is always set (`fin = 1`)
 * - RSV1/RSV2/RSV3 are unset (`0`)
 * - Control frames must not be fragmented
 * - Payload must be ≤ 125 bytes
 *
 * @param payload - Optional binary payload to include (e.g., Pong echo, Close code+reason).
 * @param opcode - The control frame opcode (`PING`, `PONG`, `CLOSE`).
 * @returns A fully constructed {@link PulseFrame} representing the control frame.
 *
 * @throws {PulseFrameError} If the payload exceeds the allowed limit for control frames.
 *
 * @example
 * ```ts
 * const pingFrame = createFrameFromControlCode(Buffer.from('ping'), PulseFrameOpcode.PING);
 * const closeFrame = createFrameFromControlCode(undefined, PulseFrameOpcode.CLOSE);
 * ```
 *
 * @see RFC 6455 §5.5 - Control Frames
 */
declare function createFrameFromControlCode(payload: Buffer | undefined, opcode: PulseFrameOpcode): PulseFrame;

/**
 * Creates a WebSocket text frame with the given UTF-8 string.
 *
 * The string is encoded as UTF-8 and inserted directly into the payload.
 * This is a convenience wrapper for quickly sending simple text messages.
 *
 * @param text - The UTF-8 string to send as the frame payload.
 * @returns A complete PulseFrame representing a text frame.
 *
 * @see RFC 6455 §5.6 - Data Frames (Text)
 */
declare function createFrameFromText(text: string): PulseFrame;

/**
 * Converts a `PulseFrame` object into a raw WebSocket frame buffer.
 *
 * This function serializes a fully constructed frame into a binary format
 * suitable for transmission over a socket, following the WebSocket framing
 * rules defined in [RFC 6455 §5.2](https://datatracker.ietf.org/doc/html/rfc6455#section-5.2).
 *
 * It handles:
 * - Base header byte construction (FIN, RSV1–3, opcode, MASK).
 * - Extended payload length encoding if necessary (16-bit or 64-bit).
 * - Optional payload masking (XOR with masking key).
 * - Concatenation of header and final payload buffer.
 *
 * @param frame - The `PulseFrame` instance to serialize.
 * @returns A `Buffer` containing the fully encoded WebSocket frame.
 *
 * @see RFC 6455 §5.2 - Base Framing Protocol
 */
declare function frameToBuffer(frame: PulseFrame): Buffer;

/**
 * Represents a protocol error encountered while parsing or constructing
 * a WebSocket frame.
 *
 * Used to signal issues such as:
 * - Invalid opcodes
 * - Malformed payloads
 * - Invalid close codes
 * - Incomplete or truncated frames
 *
 * @extends Error
 */
declare class PulseFrameError extends Error {
    readonly message: string;
    /**
     * Creates a new PulseFrameError with a specific error message.
     *
     * @param message - A descriptive explanation of the framing error.
     */
    constructor(message: string);
}

export { PulseFrame, type PulseFrameBuildOptions, PulseFrameError, type PulseFrameExtensionSupport, type PulseFrameHeader, PulseFrameOpcode, type PulseFrameOptions, createFrame, createFrameFromBuffer, createFrameFromControlCode, createFrameFromText, frameToBuffer };
