import { PlayerEvent, PlayerEvents, TrackEndEvent, TrackExceptionEvent, TrackStartEvent, TrackStuckEvent, WebSocketClosedEvent } from "./Utils";
import { Synthra, SearchPlatform } from "./Manager";
import { Player, Track } from "./Player";
import { Rest } from "./Rest";
import WebSocket from "ws";
export declare enum SponsorBlockSegment {
    Sponsor = "sponsor",
    SelfPromo = "selfpromo",
    Interaction = "interaction",
    Intro = "intro",
    Outro = "outro",
    Preview = "preview",
    MusicOfftopic = "music_offtopic",
    Filler = "filler"
}
export declare class Node {
    options: NodeOptions;
    /** The socket for the node. */
    socket: WebSocket | null;
    /** The stats for the node. */
    stats: NodeStats;
    /** The manager for the node */
    manager: Synthra;
    /** The node's session ID. */
    sessionId: string | null;
    /** The REST instance. */
    readonly rest: Rest;
    /** Actual Lavalink information of the node. */
    info: LavalinkInfo | null;
    private static _manager;
    private reconnectTimeout?;
    private reconnectAttempts;
    /**
     * Creates an instance of Node.
     * @param options
     */
    constructor(options: NodeOptions);
    /** Returns if connected to the Node. */
    get connected(): boolean;
    /** Returns the address for this node. */
    get address(): string;
    /** @hidden */
    static init(manager: Synthra): void;
    /**
     * Creates the sessionIds.json file if it doesn't exist. This file is used to
     * store the session IDs for each node. The session IDs are used to identify
     * the node when resuming a session.
     */
    createSessionIdsFile(): void;
    /**
     * Loads session IDs from the sessionIds.json file if it exists.
     * The session IDs are used to resume sessions for each node.
     *
     * The session IDs are stored in the sessionIds.json file as a composite key
     * of the node identifier and cluster ID. This allows multiple clusters to
     * be used with the same node identifier.
     */
    loadSessionIds(): void;
    /**
     * Updates the session ID in the sessionIds.json file.
     *
     * This method is called after the session ID has been updated, and it
     * writes the new session ID to the sessionIds.json file.
     *
     * @remarks
     * The session ID is stored in the sessionIds.json file as a composite key
     * of the node identifier and cluster ID. This allows multiple clusters to
     * be used with the same node identifier.
     */
    updateSessionId(): void;
    /**
     * Connects to the Node.
     *
     * @remarks
     * If the node is already connected, this method will do nothing.
     * If the node has a session ID, it will be sent in the headers of the WebSocket connection.
     * If the node has no session ID but the `resumeStatus` option is true, it will use the session ID
     * stored in the sessionIds.json file if it exists.
     */
    connect(): void;
    /**
     * Destroys the node and cleans up associated resources.
     *
     * This method emits a debug event indicating that the node is being destroyed and attempts
     * to automatically move all players connected to the node to a usable one. It then closes
     * the WebSocket connection, removes all event listeners, and clears the reconnect timeout.
     * Finally, it emits a "nodeDestroy" event and removes the node from the manager.
     *
     * @returns {Promise<void>} A promise that resolves when the node and its resources have been destroyed.
     */
    destroy(): Promise<void>;
    /**
     * Attempts to reconnect to the node if the connection is lost.
     *
     * This method is called when the WebSocket connection is closed
     * unexpectedly. It will attempt to reconnect to the node after a
     * specified delay, and will continue to do so until the maximum
     * number of retry attempts is reached or the node is manually destroyed.
     * If the maximum number of retry attempts is reached, an error event
     * will be emitted and the node will be destroyed.
     *
     * @returns {Promise<void>} - Resolves when the reconnection attempt is scheduled.
     * @emits {debug} - Emits a debug event indicating the node is attempting to reconnect.
     * @emits {nodeReconnect} - Emits a nodeReconnect event when the node is attempting to reconnect.
     * @emits {nodeError} - Emits an error event if the maximum number of retry attempts is reached.
     * @emits {nodeDestroy} - Emits a nodeDestroy event if the maximum number of retry attempts is reached.
     */
    private reconnect;
    /**
     * Handles the "open" event emitted by the WebSocket connection.
     *
     * This method is called when the WebSocket connection is established.
     * It clears any existing reconnect timeouts, emits a debug event
     * indicating the node is connected, and emits a "nodeConnect" event
     * with the node as the argument.
     */
    protected open(): void;
    /**
     * Handles the "close" event emitted by the WebSocket connection.
     *
     * This method is called when the WebSocket connection is closed.
     * It emits a "nodeDisconnect" event with the node and the close event as arguments,
     * and a debug event indicating the node is disconnected.
     * It then attempts to move all players connected to that node to a useable one.
     * If the close event was not initiated by the user, it will also attempt to reconnect.
     *
     * @param {number} code The close code of the WebSocket connection.
     * @param {string} reason The reason for the close event.
     * @returns {Promise<void>} A promise that resolves when the disconnection is handled.
     */
    protected close(code: number, reason: string): Promise<void>;
    /**
     * Handles the "error" event emitted by the WebSocket connection.
     *
     * This method is called when an error occurs on the WebSocket connection.
     * It emits a "nodeError" event with the node and the error as arguments and
     * a debug event indicating the error on the node.
     * @param {Error} error The error that occurred.
     */
    protected error(error: Error): void;
    /**
     * Handles incoming messages from the Lavalink WebSocket connection.
     * @param {Buffer | string} d The message received from the WebSocket connection.
     * @returns {Promise<void>} A promise that resolves when the message is handled.
     * @emits {debug} - Emits a debug event with the message received from the WebSocket connection.
     * @emits {nodeError} - Emits a nodeError event if an unexpected op is received.
     * @emits {nodeRaw} - Emits a nodeRaw event with the raw message received from the WebSocket connection.
     * @private
     */
    protected message(d: Buffer | string): Promise<void>;
    /**
     * Handles an event emitted from the Lavalink node.
     * @param {PlayerEvent & PlayerEvents} payload The event emitted from the node.
     * @returns {Promise<void>} A promise that resolves when the event has been handled.
     * @private
     */
    protected handleEvent(payload: PlayerEvent & PlayerEvents): Promise<void>;
    /**
     * Emitted when a new track starts playing.
     * @param {Player} player The player that started playing the track.
     * @param {Track} track The track that started playing.
     * @param {TrackStartEvent} payload The payload of the event emitted by the node.
     * @private
     */
    protected trackStart(player: Player, track: Track, payload: TrackStartEvent): void;
    /**
     * Emitted when a track ends playing.
     * @param {Player} player - The player that the track ended on.
     * @param {Track} track - The track that ended.
     * @param {TrackEndEvent} payload - The payload of the event emitted by the node.
     * @private
     */
    protected trackEnd(player: Player, track: Track, payload: TrackEndEvent): Promise<void>;
    /**
     * Handles autoplay logic for a player.
     * This method is responsible for selecting an appropriate method of autoplay
     * and executing it. If autoplay is not enabled or all attempts have failed,
     * it will return false.
     * @param {Player} player - The player to handle autoplay for.
     * @param {number} attempt - The current attempt number of the autoplay.
     * @returns {Promise<boolean>} A promise that resolves to a boolean indicating if autoplay was successful.
     * @private
     */
    private handleAutoplay;
    /**
     * Selects a platform from the given enabled sources.
     * @param {string[]} enabledSources - The enabled sources to select from.
     * @returns {SearchPlatform | null} - The selected platform or null if none was found.
     */
    selectPlatform(enabledSources: string[]): SearchPlatform | null;
    /**
     * Handles Last.fm-based autoplay.
     * @param {Player} player - The player instance.
     * @param {Track} previousTrack - The previous track.
     * @param {SearchPlatform} platform - The selected platform.
     * @param {string} apiKey - The Last.fm API key.
     * @returns {Promise<boolean>} - Whether the autoplay was successful.
     */
    private handlePlatformAutoplay;
    /**
     * Handles YouTube-based autoplay.
     * @param {Player} player - The player instance.
     * @param {Track} previousTrack - The previous track.
     * @returns {Promise<boolean>} - Whether the autoplay was successful.
     */
    private handleYouTubeAutoplay;
    /**
     * Handles the scenario when a track fails to play or load.
     * Shifts the queue to the next track and emits a track end event.
     * If there is no next track, handles the queue end scenario.
     * If autoplay is enabled, plays the next track.
     *
     * @param {Player} player - The player instance associated with the track.
     * @param {Track} track - The track that failed.
     * @param {TrackEndEvent} payload - The event payload containing details about the track end.
     * @returns {Promise<void>} A promise that resolves when the track failure has been processed.
     * @private
     */
    private handleFailedTrack;
    /**
     * Handles the scenario when a track is repeated.
     * Shifts the queue to the next track and emits a track end event.
     * If there is no next track, handles the queue end scenario.
     * If autoplay is enabled, plays the next track.
     *
     * @param {Player} player - The player instance associated with the track.
     * @param {Track} track - The track that is repeated.
     * @param {TrackEndEvent} payload - The event payload containing details about the track end.
     * @returns {Promise<void>} A promise that resolves when the repeated track has been processed.
     * @private
     */
    private handleRepeatedTrack;
    /**
     * Plays the next track in the queue.
     * Updates the queue by shifting the current track to the previous track
     * and plays the next track if autoplay is enabled.
     *
     * @param {Player} player - The player associated with the track.
     * @param {Track} track - The track that has ended.
     * @param {TrackEndEvent} payload - The event payload containing additional data about the track end event.
     * @returns {void}
     * @private
     */
    private playNextTrack;
    /**
     * Handles the event when a queue ends.
     * If autoplay is enabled, attempts to play the next track in the queue using the autoplay logic.
     * If all attempts fail, resets the player state and emits the `queueEnd` event.
     * @param {Player} player - The player associated with the track.
     * @param {Track} track - The track that has ended.
     * @param {TrackEndEvent} payload - The event payload containing additional data about the track end event.
     * @returns {Promise<void>} A promise that resolves when the queue end processing is complete.
     */
    queueEnd(player: Player, track: Track, payload: TrackEndEvent): Promise<void>;
    /**
     * Fetches the lyrics of a track from the Lavalink node.
     * This method uses the `lavalyrics-plugin` to fetch the lyrics.
     * If the plugin is not available, it will throw a RangeError.
     *
     * @param {Track} track - The track to fetch the lyrics for.
     * @param {boolean} [skipTrackSource=false] - Whether to skip using the track's source URL.
     * @returns {Promise<Lyrics>} A promise that resolves with the lyrics data.
     */
    getLyrics(track: Track, skipTrackSource?: boolean): Promise<Lyrics>;
    /**
     * Handles the event when a track becomes stuck during playback.
     * Stops the current track and emits a `trackStuck` event.
     *
     * @param {Player} player - The player associated with the track that became stuck.
     * @param {Track} track - The track that became stuck.
     * @param {TrackStuckEvent} payload - The event payload containing additional data about the track stuck event.
     * @returns {void}
     * @protected
     */
    protected trackStuck(player: Player, track: Track, payload: TrackStuckEvent): Promise<void>;
    /**
     * Handles the event when a track has an error during playback.
     * Stops the current track and emits a `trackError` event.
     *
     * @param {Player} player - The player associated with the track that had an error.
     * @param {Track} track - The track that had an error.
     * @param {TrackExceptionEvent} payload - The event payload containing additional data about the track error event.
     * @returns {void}
     * @protected
     */
    protected trackError(player: Player, track: Track, payload: TrackExceptionEvent): Promise<void>;
    /**
     * Emitted when the WebSocket connection for a player closes.
     * The payload of the event will contain the close code and reason if provided.
     * @param {Player} player - The player associated with the WebSocket connection.
     * @param {WebSocketClosedEvent} payload - The event payload containing additional data about the WebSocket close event.
     */
    protected socketClosed(player: Player, payload: WebSocketClosedEvent): void;
    /**
     * Emitted when the segments for a track are loaded.
     * The payload of the event will contain the segments.
     * @param {Player} player - The player associated with the segments.
     * @param {Track} track - The track associated with the segments.
     * @param {SponsorBlockSegmentsLoaded} payload - The event payload containing additional data about the segments loaded event.
     */
    private sponsorBlockSegmentLoaded;
    /**
     * Emitted when a segment of a track is skipped using the sponsorblock plugin.
     * The payload of the event will contain the skipped segment.
     * @param {Player} player - The player associated with the skipped segment.
     * @param {Track} track - The track associated with the skipped segment.
     * @param {SponsorBlockSegmentSkipped} payload - The event payload containing additional data about the segment skipped event.
     */
    private sponsorBlockSegmentSkipped;
    /**
     * Emitted when chapters for a track are loaded using the sponsorblock plugin.
     * The payload of the event will contain the chapters.
     * @param {Player} player - The player associated with the chapters.
     * @param {Track} track - The track associated with the chapters.
     * @param {SponsorBlockChaptersLoaded} payload - The event payload containing additional data about the chapters loaded event.
     */
    private sponsorBlockChaptersLoaded;
    /**
     * Emitted when a chapter of a track is started using the sponsorblock plugin.
     * The payload of the event will contain the started chapter.
     * @param {Player} player - The player associated with the started chapter.
     * @param {Track} track - The track associated with the started chapter.
     * @param {SponsorBlockChapterStarted} payload - The event payload containing additional data about the chapter started event.
     */
    private sponsorBlockChapterStarted;
    /**
     * Fetches Lavalink node information.
     * @returns {Promise<LavalinkInfo>} A promise that resolves to the Lavalink node information.
     */
    fetchInfo(): Promise<LavalinkInfo>;
    /**
     * Gets the current sponsorblock segments for a player.
     * @param {Player} player - The player to get the sponsorblocks for.
     * @returns {Promise<SponsorBlockSegment[]>} A promise that resolves to the sponsorblock segments.
     * @throws {RangeError} If the sponsorblock-plugin is not available in the Lavalink node.
     */
    getSponsorBlock(player: Player): Promise<SponsorBlockSegment[]>;
    /**
     * Sets the sponsorblock segments for a player.
     * @param {Player} player - The player to set the sponsor blocks for.
     * @param {SponsorBlockSegment[]} segments - The sponsorblock segments to set. Defaults to `[SponsorBlockSegment.Sponsor, SponsorBlockSegment.SelfPromo]` if not provided.
     * @returns {Promise<void>} The promise is resolved when the operation is complete.
     * @throws {RangeError} If the sponsorblock-plugin is not available in the Lavalink node.
     * @throws {RangeError} If no segments are provided.
     * @throws {SyntaxError} If an invalid sponsorblock is provided.
     * @example
     * ```ts
     * // use it on the player via player.setSponsorBlock();
     * player.setSponsorBlock([SponsorBlockSegment.Sponsor, SponsorBlockSegment.SelfPromo]);
     * ```
     */
    setSponsorBlock(player: Player, segments?: SponsorBlockSegment[]): Promise<void>;
    /**
     * Deletes the sponsorblock segments for a player.
     * @param {Player} player - The player to delete the sponsorblocks for.
     * @returns {Promise<void>} The promise is resolved when the operation is complete.
     * @throws {RangeError} If the sponsorblock-plugin is not available in the Lavalink node.
     */
    deleteSponsorBlock(player: Player): Promise<void>;
    /**
     * Creates a README.md or README.txt file in the magmastream directory
     * if it doesn't already exist. This file is used to store player data
     * for autoresume and other features.
     * @private
     */
    private createReadmeFile;
}
export interface NodeOptions {
    /** The host for the node. */
    host: string;
    /** The port for the node. */
    port?: number;
    /** The password for the node. */
    password?: string;
    /** Whether the host uses SSL. */
    secure?: boolean;
    /** The identifier for the node. */
    identifier?: string;
    /** The retryAmount for the node. */
    retryAmount?: number;
    /** The retryDelay for the node. */
    retryDelay?: number;
    /** Whether to resume the previous session. */
    resumeStatus?: boolean;
    /** The time the lavalink server will wait before it removes the player. */
    resumeTimeout?: number;
    /** The timeout used for api calls. */
    requestTimeout?: number;
    /** Priority of the node. */
    priority?: number;
}
export interface NodeStats {
    /** The amount of players on the node. */
    players: number;
    /** The amount of playing players on the node. */
    playingPlayers: number;
    /** The uptime for the node. */
    uptime: number;
    /** The memory stats for the node. */
    memory: MemoryStats;
    /** The cpu stats for the node. */
    cpu: CPUStats;
    /** The frame stats for the node. */
    frameStats: FrameStats;
}
export interface MemoryStats {
    /** The free memory of the allocated amount. */
    free: number;
    /** The used memory of the allocated amount. */
    used: number;
    /** The total allocated memory. */
    allocated: number;
    /** The reservable memory. */
    reservable: number;
}
export interface CPUStats {
    /** The core amount the host machine has. */
    cores: number;
    /** The system load. */
    systemLoad: number;
    /** The lavalink load. */
    lavalinkLoad: number;
}
export interface FrameStats {
    /** The amount of sent frames. */
    sent?: number;
    /** The amount of nulled frames. */
    nulled?: number;
    /** The amount of deficit frames. */
    deficit?: number;
}
export interface LavalinkInfo {
    version: {
        semver: string;
        major: number;
        minor: number;
        patch: number;
        preRelease: string;
    };
    buildTime: number;
    git: {
        branch: string;
        commit: string;
        commitTime: number;
    };
    jvm: string;
    lavaplayer: string;
    sourceManagers: string[];
    filters: string[];
    plugins: {
        name: string;
        version: string;
    }[];
}
export interface LyricsLine {
    timestamp: number;
    duration: number;
    line: string;
    plugin: object;
}
export interface Lyrics {
    source: string;
    provider: string;
    text?: string;
    lines: LyricsLine[];
    plugin: object[];
}
