import { BetterWs } from 'cloudstorm';
import * as discord_api_types_v10 from 'discord-api-types/v10';
import { GatewayVoiceServerUpdateDispatchData, GatewayVoiceStateUpdate, GatewayVoiceStateUpdateDispatchData } from 'discord-api-types/v10';
import { EventEmitter } from 'events';
import { PlayerState as PlayerState$1, Track, VoiceState, Filters as Filters$1, UpdatePlayerData, Player as Player$1, UpdatePlayerResult, Equalizer, DestroyPlayerResult, Stats, TrackLoadingResult, DecodeTrackResult, DecodeTracksResult, GetLavalinkVersionResult, GetLavalinkInfoResult, GetLavalinkStatsResult, UpdateSessionResult, ErrorResponse } from 'lavalink-types';
import { WebsocketMessage, PlayerState, TrackStartEvent, TrackEndEvent, TrackExceptionEvent, TrackStuckEvent, WebSocketClosedEvent, Filters } from 'lavalink-types/v4';
import { URLSearchParams } from 'url';

/**
 * Represents the voice state required for a player update, typically used when switching nodes or resuming.
 *
 * @remarks
 * This interface contains the session ID and event data needed to establish a voice connection.
 *
 * @public
 */
interface PlayerUpdateVoiceState {
    /**
     * The session ID of the voice connection.
     *
     * @readonly
     */
    sessionId: string;
    /**
     * The voice server update event data from Discord.
     *
     * @readonly
     */
    event: GatewayVoiceServerUpdateDispatchData;
    /**
     * The ID of the voice channel.
     *
     * @readonly
     */
    channelId: string;
}
/**
 * Defines the options for configuring the Lavacord Manager.
 *
 * @remarks
 * These options control how the Manager interacts with Discord and Lavalink.
 *
 * @public
 */
interface ManagerOptions {
    /**
     * The user ID of the bot.
     *
     * @remarks
     * It's recommended to set this when the bot client is ready.
     */
    userId?: string;
    /**
     * The Player class to be used by the manager for creating new player instances.
     *
     * @remarks
     * Allows for extending the base Player functionality with custom implementations.
     */
    player?: typeof Player;
    /**
     * The function used to send gateway voice packets to Discord.
     *
     * @remarks
     * This needs to be implemented by the end-user based on their Discord library.
     *
     * @param packet - The Discord packet to send.
     * @returns A Promise or value representing the send operation result.
     */
    send?: (packet: GatewayVoiceStateUpdate) => unknown;
}
/**
 * Defines the data required to join a voice channel.
 *
 * @remarks
 * Contains the essential identifiers for connecting to a specific voice channel.
 *
 * @public
 */
interface JoinData {
    /**
     * The ID of the guild where the voice channel is located.
     *
     * @readonly
     */
    guild: string;
    /**
     * The ID of the voice channel to join.
     *
     * @readonly
     */
    channel: string;
    /**
     * The ID of the LavalinkNode to use for this connection.
     *
     * @remarks
     * This determines which Lavalink server will handle the audio for this connection.
     *
     * @readonly
     */
    node: string;
}
/**
 * Defines the options for joining a voice channel.
 *
 * @remarks
 * Controls the initial state of the bot when connecting to a voice channel.
 *
 * @public
 */
interface JoinOptions {
    /**
     * Whether the bot should be self-muted upon joining the voice channel.
     *
     * @defaultValue false
     */
    selfmute?: boolean;
    /**
     * Whether the bot should be self-deafened upon joining the voice channel.
     *
     * @defaultValue false
     */
    selfdeaf?: boolean;
}
/**
 * Defines the options for configuring a LavalinkNode.
 *
 * @remarks
 * These options specify how to connect to a Lavalink server and how the node should behave.
 *
 * @public
 */
interface LavalinkNodeOptions {
    /**
     * A unique identifier for this LavalinkNode, used for organization.
     *
     * @remarks
     * This ID is used internally by Lavacord to reference and manage nodes.
     *
     * @readonly
     */
    id: string;
    /**
     * The hostname or IP address of the Lavalink server.
     *
     * @defaultValue "localhost"
     */
    host: string;
    /**
     * The port number of the Lavalink server.
     *
     * @defaultValue 2333
     */
    port?: number | string;
    /**
     * The password for authenticating with the Lavalink server.
     *
     * @defaultValue "youshallnotpass"
     */
    password?: string;
    /**
     * The interval (in milliseconds) at which the node will attempt to reconnect if the connection is lost.
     *
     * @defaultValue 10000 (10 seconds)
     */
    reconnectInterval?: number;
    /**
     * A previous session ID to attempt to resume a connection with the Lavalink server.
     *
     * @remarks
     * This is used when attempting to resume a previous session after reconnection.
     */
    sessionId?: string;
    /**
     * Whether the node should attempt to resume the session if a `sessionId` is present when the WebSocket connection opens or the node becomes ready.
     *
     * @defaultValue false
     */
    resuming?: boolean;
    /**
     * The timeout (in seconds) for resuming a session.
     *
     * @defaultValue 120 (2 minutes)
     */
    resumeTimeout?: number;
    /**
     * Whether to use secure connections (HTTPS/WSS) instead of HTTP/WS.
     *
     * @remarks
     * When true, WebSocket connections will use WSS and REST requests will use HTTPS.
     * This is required when connecting to Lavalink servers behind SSL/TLS.
     *
     * @defaultValue false
     */
    secure?: boolean;
    /**
     * Arbitrary state data that can be attached to the node for user-specific purposes.
     *
     * @remarks
     * This data is not sent to Lavalink and is only used internally.
     */
    state?: unknown;
}
/**
 * Type definition for Manager events.
 */
interface ManagerEvents {
    /**
     * Emitted when a node becomes ready.
     * @event
     */
    ready: [LavalinkNode];
    /**
     * Emitted for all raw messages from Lavalink.
     * @event
     */
    raw: [WebsocketMessage, LavalinkNode];
    /**
     * Emitted when a node encounters an error.
     * @event
     */
    error: [unknown, LavalinkNode];
    /**
     * Emitted when a node disconnects.
     * @event
     */
    disconnect: [number, string, LavalinkNode];
    /**
     * Emitted when a node is attempting to reconnect.
     * @event
     */
    reconnecting: [LavalinkNode];
    /**
     * Represents Lavalink's playerUpdate event.
     * emits every x time as defined by the lavalink server.
     * @see {@link https://lavalink.dev/api/websocket.html#player-update-op}
     * @event
     */
    playerState: [Player, PlayerState];
    /**
     * Emitted when a track starts playing.
     * @see {@link https://lavalink.dev/api/websocket.html#trackstartevent}
     * @event
     */
    playerTrackStart: [Player, TrackStartEvent];
    /**
     * Emitted when a track ends.
     * @see {@link https://lavalink.dev/api/websocket.html#trackendevent}
     * @event
     */
    playerTrackEnd: [Player, TrackEndEvent];
    /**
     * Emitted when a track encounters an exception.
     * @see {@link https://lavalink.dev/api/websocket.html#trackexceptionevent}
     * @event
     */
    playerTrackException: [Player, TrackExceptionEvent];
    /**
     * Emitted when a track gets stuck.
     * @see {@link https://lavalink.dev/api/websocket.html#trackstuckevent}
     * @event
     */
    playerTrackStuck: [Player, TrackStuckEvent];
    /**
     * Emitted when the voice WebSocket is closed.
     * @see {@link https://lavalink.dev/api/websocket.html#websocketclosedevent}
     * @event
     */
    playerWebSocketClosed: [Player, WebSocketClosedEvent];
    /**
     * Emitted for warnings.
     * @event
     */
    warn: [string];
    /**
     * Emitted when a player is paused or resumed.
     * @event
     */
    playerPause: [Player, boolean];
    /**
     * Emitted when a player's volume changes.
     * @event
     */
    playerVolume: [Player, number];
    /**
     * Emitted when a player seeks to a position.
     * @event
     */
    playerSeek: [Player, number];
    /**
     * Emitted when a player updates its filters.
     * @event
     */
    playerFilters: [Player, Filters];
}
interface PlayerEvents {
    /**
     * Represents Lavalink's playerUpdate event.
     * emits every x time as defined by the lavalink server.
     * @see {@link https://lavalink.dev/api/websocket.html#player-update-op}
     * @event
     */
    state: [PlayerState];
    /**
     * Emitted when a track starts playing.
     * @see {@link https://lavalink.dev/api/websocket.html#trackstartevent}
     * @event
     */
    trackStart: [TrackStartEvent];
    /**
     * Emitted when a track ends.
     * @see {@link https://lavalink.dev/api/websocket.html#trackendevent}
     * @event
     */
    trackEnd: [TrackEndEvent];
    /**
     * Emitted when a track encounters an exception.
     * @see {@link https://lavalink.dev/api/websocket.html#trackexceptionevent}
     * @event
     */
    trackException: [TrackExceptionEvent];
    /**
     * Emitted when a track gets stuck.
     * @see {@link https://lavalink.dev/api/websocket.html#trackstuckevent}
     * @event
     */
    trackStuck: [TrackStuckEvent];
    /**
     * Emitted when the voice WebSocket is closed.
     * @see {@link https://lavalink.dev/api/websocket.html#websocketclosedevent}
     * @event
     */
    webSocketClosed: [WebSocketClosedEvent];
    /**
     * Emitted when the player is paused or resumed.
     * @event
     */
    pause: [boolean];
    /**
     * Emitted when the player seeks to a position.
     * @event
     */
    seek: [number];
    /**
     * Emitted when the player volume changes.
     * @event
     */
    volume: [number];
    /**
     * Emitted when the player updates its filters.
     * @event
     */
    filters: [Filters];
}

/**
 * The Player class that handles playback and audio manipulation for a specific guild.
 *
 * @remarks
 * This class is responsible for audio playback operations, including playing, stopping,
 * pausing, resuming, and applying audio filters. Each instance represents a player
 * for a specific guild.
 */
declare class Player extends EventEmitter<PlayerEvents> {
    /**
     * The Lavalink node this player is connected to
     */
    node: LavalinkNode;
    /**
     * The guild ID for this player
     */
    guildId: string;
    /**
     * The current state of this Player
     *
     * @remarks
     * Contains information about the player state from Lavalink, including position, filters, etc.
     */
    state: PlayerState$1;
    /**
     * The timestamp when the current track started playing
     *
     * @remarks
     * This is a client-side timestamp, not synchronized with Lavalink.
     * Can be used to calculate approximate playback position.
     */
    timestamp: number | null;
    /**
     * Whether the audio playback is currently paused
     */
    paused: boolean;
    /**
     * The current volume level (0-1000)
     */
    volume: number;
    /**
     * The current track in Lavalink's base64 string form
     *
     * @remarks
     * This is null when no track is loaded or when playback has ended.
     */
    track: Track | null;
    /**
     * The voice connection state from Lavalink API
     */
    voice: VoiceState | null;
    /**
     * The current audio filters applied to this player
     *
     * @remarks
     * This includes effects like equalizer, karaoke, etc.
     */
    filters: Filters$1;
    /**
     * Creates a new player instance.
     *
     * @param node - The Lavalink node this player is connected to.
     * @param guildId - The guild ID that this player is associated with.
     */
    constructor(
    /**
     * The Lavalink node this player is connected to
     */
    node: LavalinkNode, 
    /**
     * The guild ID for this player
     */
    guildId: string);
    /**
     * Updates the current player on the Lavalink node.
     * @see {@link https://lavalink.dev/api/rest#update-player}
     *
     * @param options - The update options to apply to the player.
     * @param noReplace - If true, the event will be dropped if there's a currently playing track.
     * @returns {Promise<APIPlayer>} The updated player information from Lavalink.
     */
    update(options: UpdatePlayerData, noReplace?: boolean): Promise<Player$1>;
    /**
     * Plays a track using its base64 encoded string.
     *
     * @param track - The base64 encoded track string from Lavalink.
     * @param options - Additional options for playback.
     * @returns A promise resolving to the updated player information.
     */
    play(track: string, options?: Omit<UpdatePlayerData, "track"> & {
        noReplace?: boolean;
        userData?: Record<any, any>;
    }): Promise<UpdatePlayerResult>;
    /**
     * Stops the currently playing track.
     *
     * @remarks
     * This will trigger a "TrackEndEvent" with reason "STOPPED".
     *
     * @returns A promise resolving to the updated player information.
     */
    stop(): Promise<UpdatePlayerResult>;
    /**
     * Pauses or resumes the current track.
     *
     * @param pause - Whether to pause (true) or resume (false) playback.
     * @returns A promise resolving to the updated player information.
     */
    pause(pause: boolean): Promise<UpdatePlayerResult>;
    /**
     * Changes the volume of the current playback.
     *
     * @param volume - The volume level as a number between 0 and 1000
     * @returns A promise resolving to the updated player information.
     */
    setVolume(volume: number): Promise<UpdatePlayerResult>;
    /**
     * Seeks to a specific position in the current track.
     *
     * @param position - The position to seek to in milliseconds.
     * @returns A promise resolving to the updated player information.
     */
    seek(position: number): Promise<UpdatePlayerResult>;
    /**
     * Applies audio filters to the current playback.
     *
     * @param options - The filter options to apply.
     * @returns A promise resolving to the updated player information.
     */
    setFilters(options: Filters$1): Promise<UpdatePlayerResult>;
    /**
     * Sets the equalizer effect for the current playback.
     *
     * @param bands - An array of equalizer bands to adjust.
     * @returns A promise resolving to the updated player information.
     *
     * @remarks
     * Each band is an object with 'band' (0-14) and 'gain' (-0.25 to 1.0) properties.
     */
    setEqualizer(bands: Equalizer[]): Promise<UpdatePlayerResult>;
    /**
     * Destroys the player on the Lavalink node.
     *
     * @remarks
     * This sends a destroy signal to Lavalink to clean up resources for this guild ID.
     * It doesn't affect the Discord voice connection - use {@link Manager.leave} for that.
     *
     * @returns {Promise<DestroyPlayerResult>} A promise resolving to the destroy result.
     */
    destroy(): Promise<DestroyPlayerResult>;
    /**
     * Provides voice server update information to Lavalink to establish a connection.
     *
     * @param data - The voice update state containing session ID and voice server information.
     * @returns A promise resolving to the updated player information.
     */
    connect(data: PlayerUpdateVoiceState): Promise<UpdatePlayerResult>;
    /**
     * Switches the player to a different voice channel.
     *
     * @param channel - The ID of the voice channel to switch to.
     * @param options - Options for joining the channel (selfMute, selfDeaf).
     * @returns Does not return anything, but sends a WebSocket message to the Lavalink node.
     */
    switchChannel(channel: string, options?: JoinOptions): unknown;
    /**
     * Gets the manager instance that created this player.
     *
     * @returns {Manager} The manager instance.
     */
    get manager(): Manager;
}

/**
 * Main class that handles Lavalink node connections and player management.
 *
 * @remarks
 * The Manager acts as the central hub for Lavacord, managing connections to Lavalink nodes,
 * handling voice state updates, and providing a unified interface for player operations.
 */
declare class Manager extends EventEmitter<ManagerEvents> {
    /**
     * A Map of Lavalink Nodes indexed by their IDs.
     */
    nodes: Map<string, LavalinkNode>;
    /**
     * A Map of all active players indexed by guild ID.
     */
    players: Map<string, Player>;
    /**
     * A Map of voice server update states indexed by guild ID.
     */
    voiceServers: Map<string, GatewayVoiceServerUpdateDispatchData>;
    /**
     * A Map of voice state update states indexed by guild ID.
     */
    voiceStates: Map<string, discord_api_types_v10.APIVoiceState>;
    /**
     * The user ID of the bot this Manager is managing.
     */
    userId: string | null;
    /**
     * Function to send voice state update packets to Discord.
     *
     * @remarks
     * This can be implemented by the user in two ways:
     * 1. Via constructor options: `new Manager(nodes, { send: fn })`
     * 2. Via class extension: `class MyManager extends Manager { send(packet) { ... } }`
     */
    private _send?;
    /**
     * The Player class constructor used when creating new players.
     *
     * @remarks
     * Can be overridden in the manager options to use a custom Player implementation.
     */
    private readonly Player;
    /**
     * A Set of guild IDs that are waiting for a connection.
     *
     * @internal
     */
    private readonly expecting;
    /**
     * Creates a new Manager instance.
     *
     * @param nodes - An array of Lavalink node options to connect to.
     * @param options - Configuration options for the Manager.
     *
     * @example
     * ```typescript
     * // Method 1: Define send function via options
     * const manager = new Manager([
     *   {
     *     id: "main",
     *     host: "localhost",
     *     port: 2333,
     *     password: "youshallnotpass"
     *   }
     * ], {
     *   userId: "bot_user_id",
     *   send: (packet) => {
     *     const guild = client.guilds.cache.get(packet.d.guild_id);
     *     if (guild) guild.shard.send(packet);
     *   }
     * });
     *
     * // Method 2: Extend Manager class
     * class MyManager extends Manager {
     *   send(packet) {
     *     const guild = this.client.guilds.cache.get(packet.d.guild_id);
     *     if (guild) guild.shard.send(packet);
     *   }
     * }
     * const manager = new MyManager(nodes, { userId: "bot_user_id" });
     * ```
     */
    constructor(nodes: LavalinkNodeOptions[], options?: ManagerOptions);
    /**
     * Connects all Lavalink nodes to their respective Lavalink servers.
     *
     * @returns A promise that resolves when all connections are established.
     *
     * @example
     * ```typescript
     * // Connect all nodes
     * manager.connect()
     *   .then(() => console.log('All nodes connected!'))
     *   .catch(error => console.error('Failed to connect nodes:', error));
     * ```
     */
    connect(): Promise<LavalinkNode[]>;
    /**
     * Disconnects all players and nodes, effectively cleaning up all resources.
     *
     * @returns A promise that resolves when all disconnections are complete.
     *
     * @example
     * ```typescript
     * // Disconnect everything
     * manager.disconnect()
     *   .then(() => console.log('All players and nodes cleaned up'))
     *   .catch(error => console.error('Error during disconnection:', error));
     * ```
     */
    disconnect(): Promise<void>;
    /**
     * Creates a new Lavalink node and adds it to the nodes map.
     *
     * @param options - Configuration options for the node.
     * @returns The newly created LavalinkNode instance.
     *
     * @example
     * ```typescript
     * // Add a new node
     * const newNode = manager.createNode({
     *   id: "node2",
     *   host: "example.com",
     *   port: 2333,
     *   password: "securepassword",
     *   resuming: true
     * });
     * ```
     */
    createNode(options: LavalinkNodeOptions): LavalinkNode;
    /**
     * Disconnects and removes a node from the manager.
     *
     * @param id - The ID of the node to remove.
     * @returns Whether the node was successfully removed.
     *
     * @example
     * ```typescript
     * // Remove a node
     * const removed = manager.removeNode("node1");
     * if (removed) {
     *   console.log("Node successfully removed");
     * } else {
     *   console.log("Node not found");
     * }
     * ```
     */
    removeNode(id: string): boolean;
    /**
     * Joins a voice channel and creates a player for the guild.
     *
     * @param data - The data needed to join a voice channel.
     * @param joinOptions - Options for joining the channel (selfmute, selfdeaf).
     * @returns A promise resolving to the Player instance.
     *
     * @example
     * ```typescript
     * // Join a voice channel
     * const player = await manager.join({
     *   guild: "123456789012345678", // Guild ID
     *   channel: "123456789012345679", // Voice Channel ID
     *   node: "main" // Node ID
     * }, {
     *   selfdeaf: true // Join deafened
     * });
     *
     * // Now you can use the player to play music
     * const result = await Rest.load(player.node, "https://www.youtube.com/watch?v=dQw4w9WgXcQ");
     * await player.play(result.tracks[0].track);
     * ```
     */
    join(data: JoinData, joinOptions?: JoinOptions): Promise<Player>;
    /**
     * Leaves a voice channel and cleans up the player.
     *
     * @param guild - The ID of the guild to leave.
     * @returns A promise resolving to whether the operation was successful.
     *
     * @example
     * ```typescript
     * // Leave a voice channel
     * const success = await manager.leave("123456789012345678");
     * if (success) {
     *   console.log("Successfully left the voice channel");
     * } else {
     *   console.log("Not in a voice channel in this guild");
     * }
     * ```
     */
    leave(guild: string): Promise<boolean>;
    /**
     * Switches a player from one node to another, implementing fallback capability.
     *
     * @param player - The player to move to another node.
     * @param node - The destination node.
     * @returns A promise resolving to the updated player.
     *
     * @example
     * ```typescript
     * // Switch a player to another node (e.g. if current node is failing)
     * const player = manager.players.get("123456789012345678");
     * const newNode = manager.nodes.get("backup-node");
     *
     * if (player && newNode) {
     *   await manager.switch(player, newNode);
     *   console.log("Player switched to backup node");
     * }
     * ```
     */
    switch(player: Player, node: LavalinkNode): Promise<Player>;
    /**
     * Processes voice server update events from Discord.
     *
     * @param data - The voice server update data from Discord.
     * @returns A promise resolving to whether a connection was established.
     *
     * @example
     * ```typescript
     * // In your Discord.js client events
     * client.ws.on(GatewayDispatchEvents.VoiceServerUpdate, (data) => {
     *   manager.voiceServerUpdate(data);
     * });
     * ```
     */
    voiceServerUpdate(data: GatewayVoiceServerUpdateDispatchData): Promise<boolean>;
    /**
     * Processes voice state update events from Discord.
     *
     * @param data - The voice state update data from Discord.
     * @returns A promise resolving to whether a connection was established.
     *
     * @example
     * ```typescript
     * // In your Discord.js client events
     * client.ws.on(GatewayDispatchEvents.VoiceStateUpdate, (data) => {
     *   manager.voiceStateUpdate(data);
     * });
     * ```
     */
    voiceStateUpdate(data: GatewayVoiceStateUpdateDispatchData): Promise<boolean>;
    /**
     * Sends a voice state update packet to Discord.
     *
     * @param guild - The ID of the guild.
     * @param channel - The ID of the voice channel to join, or null to leave.
     * @param options - Options for joining (selfmute, selfdeaf).
     * @returns The result from the send function.
     *
     * @example
     * ```typescript
     * // Join a voice channel
     * manager.sendWS("123456789012345678", "123456789012345679", { selfdeaf: true });
     *
     * // Leave a voice channel
     * manager.sendWS("123456789012345678", null);
     * ```
     */
    sendWS(guild: string, channel: string | null, { selfmute, selfdeaf }?: JoinOptions): unknown;
    /**
     * Gets all connected nodes, sorted by CPU load.
     *
     * @returns An array of connected nodes sorted by CPU load (least to most).
     *
     * @example
     * ```typescript
     * // Get the node with the least CPU load
     * const bestNode = manager.idealNodes[0];
     * if (bestNode) {
     *   console.log(`Best node for new connections: ${bestNode.id}`);
     * }
     * ```
     */
    get idealNodes(): LavalinkNode[];
    /**
     * Attempts to establish a connection for a guild using available voice data.
     *
     * @internal
     * @param guildID - The ID of the guild to attempt connecting.
     * @returns A promise resolving to whether a connection was established.
     */
    private _attemptConnection;
    /**
     * Creates a new player instance.
     *
     * @internal
     * @param data - The data needed to create a player.
     * @returns The created Player instance.
     */
    private spawnPlayer;
    protected send(packet: GatewayVoiceStateUpdate): unknown;
}

/**
 * The LavalinkNode class handles the connection and communication with a Lavalink server.
 *
 * @summary Manages WebSocket connections to Lavalink servers and processes server events
 *
 * This class is responsible for establishing WebSocket connections to Lavalink,
 * handling reconnection logic, and processing incoming messages from the server.
 *
 * @remarks
 * LavalinkNode instances are typically created and managed by the {@link Manager} class,
 * which handles load balancing across multiple nodes and routing player actions
 * to the appropriate node.
 */
declare class LavalinkNode {
    manager: Manager;
    /**
     * The identifier for this Lavalink node. Used to distinguish between multiple nodes.
     *
     * @summary Unique identifier for the node
     * @remarks
     * This is a required property that must be unique across all nodes in your application.
     * It's used for identifying this node in logs and when selecting nodes for new players.
     */
    id: string;
    /**
     * The hostname or IP address of the Lavalink server.
     *
     * @summary Server hostname or IP address
     * @remarks
     * This can be a domain name, IPv4, or IPv6 address pointing to your Lavalink server.
     */
    readonly host = "localhost";
    /**
     * The port number that the Lavalink server is listening on.
     *
     * @summary Server port number
     * @remarks
     * This should match the port configured in your Lavalink server's application.yml.
     */
    readonly port: number | string;
    /**
     * The time in milliseconds between reconnection attempts if the connection fails.
     *
     * @summary Reconnection delay in milliseconds
     * @remarks
     * Lower values will attempt reconnections more quickly, but might
     * cause excessive connection attempts during prolonged server outages.
     */
    reconnectInterval: number;
    /**
     * The password used for authorization with the Lavalink server.
     *
     * @summary Authorization password for the Lavalink server
     * @remarks
     * This password must match the one configured in your Lavalink server's application.yml.
     * It's used in the Authorization header when establishing the WebSocket connection.
     */
    readonly password = "youshallnotpass";
    /**
     * Whether to use secure connections (HTTPS/WSS) instead of HTTP/WS.
     *
     * @summary Secure connection flag for SSL/TLS
     * @remarks
     * When true, WebSocket connections will use WSS and REST requests will use HTTPS.
     * This is required when connecting to Lavalink servers behind SSL/TLS.
     */
    readonly secure = false;
    /**
     * The WebSocket instance used for communication with the Lavalink server.
     *
     * @summary Active WebSocket connection to the Lavalink server
     * @remarks
     * When not connected to Lavalink, this property will be null.
     * You can check the {@link connected} property to determine connection status.
     */
    ws: BetterWs | null;
    /**
     * The statistics received from the Lavalink server.
     *
     * @summary Server resource usage and player statistics
     * @remarks
     * Contains information about system resource usage, player counts, and audio frame statistics.
     * This is updated whenever the Lavalink server sends a stats update (typically every minute).
     * You can use these stats to implement node selection strategies in your application.
     */
    stats: Stats;
    /**
     * Whether this node should attempt to resume the session when reconnecting.
     *
     * @summary Session resumption flag
     * @remarks
     * When true, the node will try to resume the previous session after a disconnect,
     * preserving player states and connections. This helps maintain playback during
     * brief disconnections or node restarts.
     */
    resuming: boolean;
    /**
     * The timeout in seconds after which a disconnected session can no longer be resumed.
     *
     * @summary Maximum session resumption timeout in seconds
     * @remarks
     * This value is sent to the Lavalink server when configuring session resuming.
     * After this many seconds of disconnection, the session will be fully closed
     * and cannot be resumed.
     */
    resumeTimeout: number;
    /**
     * Custom data that can be attached to the node instance.
     *
     * @summary Custom application data storage
     * @remarks
     * Not used internally by Lavacord, available for application-specific needs.
     * You can use this property to store any data relevant to your implementation,
     * such as region information, feature flags, or custom metrics.
     */
    state?: any;
    /**
     * The unique session identifier provided by Lavalink on successful connection.
     *
     * @summary Lavalink session identifier
     * @remarks
     * This ID is used for resuming sessions and in certain REST API calls.
     * It's automatically assigned when connecting to the Lavalink server.
     */
    sessionId?: string;
    /**
     * The version of the Lavalink protocol this node is using.
     *
     * @summary Lavalink protocol version
     * @remarks
     * This is set automatically when connecting to the Lavalink server.
     * It indicates which version of the Lavalink protocol this node supports.
     * The default value is "4", which corresponds to the latest stable version.
     *
     * @defaultValue "4"
     */
    version: string;
    /**
     * Timeout reference used for the reconnection mechanism.
     * This holds the NodeJS.Timeout instance used to schedule reconnection attempts.
     */
    private _reconnect?;
    /**
     * Current reconnection attempt count for exponential backoff.
     */
    private _reconnectAttempts;
    /**
     * Tracks whether the session has been updated with the Lavalink server.
     * Used internally to avoid redundant session update requests.
     */
    private _sessionUpdated;
    /**
     * Creates a new LavalinkNode instance.
     *
     * @summary Initializes a new Lavalink node connection
     * @param manager - The {@link Manager} instance that controls this node
     * @param options - Configuration options for this Lavalink node as defined in {@link LavalinkNodeOptions}
     */
    constructor(manager: Manager, options: LavalinkNodeOptions);
    /**
     * Establishes a connection to the Lavalink server.
     *
     * This method creates a new WebSocket connection to the configured Lavalink server.
     * If the node is already connected, it will close the existing connection first.
     * The method sets up event listeners for the WebSocket to handle messages, errors,
     * and connection state changes.
     *
     * Note: This method is primarily used internally by the {@link Manager} class.
     * Users typically should not call this method directly as the Manager handles
     * node connections automatically.
     *
     * @returns A promise that resolves when connected or rejects if connection fails
     * @throws {Error} If the connection fails due to network issues, authentication problems, or other errors
     */
    connect(): Promise<BetterWs>;
    /**
     * Gracefully closes the connection to the Lavalink server.
     *
     * This method closes the WebSocket connection with a normal closure code (1000)
     * and a reason of "destroy", indicating an intentional disconnection rather
     * than an error condition.
     *
     * Note: This method is primarily used internally by the {@link Manager} class.
     * Users typically should not call this method directly as the Manager handles
     * node disconnections automatically.
     *
     * @returns void
     */
    destroy(): void;
    /**
     * Indicates whether this node is currently connected to the Lavalink server.
     *
     * @summary Connection status check
     * @remarks
     * Checks if the {@link ws} instance exists and if its ready state is 1.
     * This property is useful for verifying connection status before attempting operations
     * or implementing node selection strategies.
     *
     * @returns `true` if connected, `false` otherwise
     */
    get connected(): boolean;
    /**
     * Gets the WebSocket URL for connecting to the Lavalink server.
     *
     * @summary WebSocket connection URL
     * @remarks
     * Returns either a secure (wss://) or insecure (ws://) WebSocket URL
     * based on the {@link secure} property configuration.
     *
     * @returns The complete WebSocket URL including protocol, host, port, and path
     */
    get socketURL(): string;
    /**
     * Gets the REST API base URL for the Lavalink server.
     *
     * @summary REST API base URL
     * @remarks
     * Returns either a secure (https://) or insecure (http://) REST URL
     * based on the {@link secure} property configuration.
     *
     * @returns The complete REST API base URL including protocol, host, port, and path
     */
    get restURL(): string;
    /**
     * Handles the WebSocket 'open' event when a connection is established.
     */
    private onOpen;
    /**
     * Processes incoming WebSocket messages from the Lavalink server.
     * @param msg - The raw data received from the WebSocket
     */
    private onMessage;
    /**
     * Handles WebSocket errors.
     * @param error - The error received from the WebSocket
     */
    private onError;
    /**
     * Handles WebSocket closure.
     *
     * @param code - The WebSocket close code (see Lavalink API for code meanings)
     * @param reason - The reason why the WebSocket was closed
     */
    private onClose;
    /**
     * Initiates a reconnection attempt after a delay with exponential backoff.
     */
    private reconnect;
    private _handleEvent;
}

/**
 * Error class for Lavalink REST API errors.
 * @remarks
 * Contains the full error response from the Lavalink server.
 * See {@link https://lavalink.dev/api/rest#error-responses}
 * @public
 */
declare class RestError extends Error {
    error: ErrorResponse;
    data: RequestInit;
    constructor(error: ErrorResponse, data: RequestInit);
}
/**
 * A utility class for interacting with the Lavalink REST API.
 *
 * @remarks
 * Provides methods to perform various operations on a Lavalink server through its REST API,
 * including loading tracks, decoding tracks, and controlling players.
 *
 * @public
 * @sealed
 */
declare class Rest {
    /**
     * Base request function that handles communication with Lavalink REST API.
     *
     * @internal
     * @param node - The Lavalink node to send the request to.
     * @param path - The API route path, starting with /.
     * @param init - Optional request initialization options.
     * @param requiresSessionId - Whether the request requires a valid session ID.
     * @returns A promise resolving to the response data.
     * @throws {@link RestError} If Lavalink returns an error response.
     */
    private static baseRequest;
    /**
     * Loads tracks from various sources using Lavalink's loadtracks endpoint.
     *
     * @param node - The Lavalink node to use.
     * @param identifer - The identifier to load tracks from (URL, search query, etc.)
     * @returns A promise resolving to the track loading result.
     * @throws {@link RestError} If Lavalink encounters an error.
     *
     * @public
     */
    static load(node: LavalinkNode, identifer: string): Promise<TrackLoadingResult>;
    /**
     * Decodes track(s) from their base64 encoded form.
     *
     * @param node - The Lavalink node to use.
     * @param track - A single track to decode.
     * @returns A promise resolving to the decoded track information.
     * @throws {@link RestError} If Lavalink encounters an error.

     * @public
     */
    static decode(node: LavalinkNode, track: string): Promise<DecodeTrackResult>;
    /**
     * Decodes multiple tracks from their base64 encoded form.
     *
     * @param node - The Lavalink node to use.
     * @param tracks - An array of tracks to decode.
     * @returns A promise resolving to an array of decoded track information.
     * @throws {@link RestError} If Lavalink encounters an error.
     *
     * @public
     */
    static decode(node: LavalinkNode, tracks: string[]): Promise<DecodeTracksResult>;
    /**
     * Retrieves the version from the Lavalink server.
     *
     * @param node - The Lavalink node to query.
     * @returns A promise resolving to the version of lavalink.
     * @throws {@link RestError} If Lavalink encounters an error.
     *
     * @public
     */
    static version(node: LavalinkNode): Promise<GetLavalinkVersionResult>;
    /**
     * Retrieves the information of the Lavalink server.
     *
     * @param node - The Lavalink node to query.
     * @returns A promise resolving to the information of lavalink.
     * @throws {@link RestError} If Lavalink encounters an error.
     *
     * @public
     */
    static info(node: LavalinkNode): Promise<GetLavalinkInfoResult>;
    /**
     * Retrieves the statistics of the Lavalink node.
     *
     * @param node - The Lavalink node to query.
     * @returns A promise resolving to the statistics of lavalink.
     * @throws {@link RestError} If Lavalink encounters an error.
     *
     * @public
     */
    static stats(node: LavalinkNode): Promise<GetLavalinkStatsResult>;
    /**
     * Updates the session properties of a Lavalink node.
     *
     * @param node - The Lavalink node to update.
     * @returns A promise resolving to the update session result.
     * @throws {@link RestError} If Lavalink encounters an error.
     *
     * @public
     */
    static updateSession(node: LavalinkNode): Promise<UpdateSessionResult>;
    /**
     * Updates a player on a Lavalink node.
     *
     * @param node - The Lavalink node hosting the player.
     * @param guildId - The guild ID associated with the player.
     * @param data - The player update data.
     * @param noReplace - If true, the event will be dropped if there's a currently playing track.
     * @returns A promise resolving to the updated player information.
     * @throws {@link RestError} If Lavalink encounters an error.

     * @public
     */
    static updatePlayer(node: LavalinkNode, guildId: string, data: UpdatePlayerData, noReplace?: boolean): Promise<UpdatePlayerResult>;
    /**
     * Destroys a player on a Lavalink node.
     *
     * @param node - The Lavalink node hosting the player.
     * @param guildId - The guild ID associated with the player to destroy.
     * @returns A promise resolving to the destroy player result.
     * @throws {@link RestError} If Lavalink encounters an error.
     *
     * @public
     */
    static destroyPlayer(node: LavalinkNode, guildId: string): Promise<DestroyPlayerResult>;
}
interface BaseRequestInit extends RequestInit {
    query?: string | URLSearchParams | Record<string, string> | [string, string][];
}

/**
 * @module Lavacord
 */

declare const VERSION: string;

export { LavalinkNode, Manager, Player, Rest, RestError, VERSION };
export type { BaseRequestInit, JoinData, JoinOptions, LavalinkNodeOptions, ManagerEvents, ManagerOptions, PlayerEvents, PlayerUpdateVoiceState };
