import { BaseExtractor, SearchQueryType, Track, GuildQueueHistory, ExtractorInfo, ExtractorSearchContext, ExtractorStreamable } from 'discord-player';
import * as SoundCloud from 'soundcloud.ts';
import * as fs from 'fs';
import { Readable } from 'stream';
import { HTMLElement } from 'node-html-parser';
import { RequestOptions } from 'http';

interface SoundCloudExtractorInit {
    clientId?: string;
    oauthToken?: string;
    proxy?: string;
}
declare class SoundCloudExtractor extends BaseExtractor<SoundCloudExtractorInit> {
    static identifier: "com.discord-player.soundcloudextractor";
    static instance: SoundCloudExtractor | null;
    internal: SoundCloud.Soundcloud;
    activate(): Promise<void>;
    deactivate(): Promise<void>;
    validate(query: string, type?: SearchQueryType | null | undefined): Promise<boolean>;
    getRelatedTracks(track: Track, history: GuildQueueHistory): Promise<ExtractorInfo>;
    handle(query: string, context: ExtractorSearchContext): Promise<ExtractorInfo>;
    emptyResponse(): ExtractorInfo;
    stream(info: Track): Promise<string>;
    bridge(track: Track, sourceExtractor: BaseExtractor | null): Promise<ExtractorStreamable | null>;
}

declare function lyricsExtractor(): void;

declare class VimeoExtractor extends BaseExtractor {
    static identifier: "com.discord-player.vimeoextractor";
    validate(query: string, type?: SearchQueryType | null | undefined): Promise<boolean>;
    getRelatedTracks(track: Track): Promise<ExtractorInfo>;
    handle(query: string, context: ExtractorSearchContext): Promise<ExtractorInfo>;
    emptyResponse(): ExtractorInfo;
    stream(info: Track): Promise<string>;
}

declare class ReverbnationExtractor extends BaseExtractor {
    static identifier: "com.discord-player.reverbnationextractor";
    validate(query: string, type?: SearchQueryType | null | undefined): Promise<boolean>;
    getRelatedTracks(track: Track): Promise<ExtractorInfo>;
    handle(query: string, context: ExtractorSearchContext): Promise<ExtractorInfo>;
    emptyResponse(): ExtractorInfo;
    stream(info: Track): Promise<string>;
}

declare class AttachmentExtractor extends BaseExtractor {
    static identifier: "com.discord-player.attachmentextractor";
    priority: number;
    validate(query: string, type?: SearchQueryType | null | undefined): Promise<boolean>;
    getRelatedTracks(track: Track): Promise<ExtractorInfo>;
    handle(query: string, context: ExtractorSearchContext): Promise<ExtractorInfo>;
    emptyResponse(): ExtractorInfo;
    stream(info: Track): Promise<string | {
        stream: fs.ReadStream;
        $fmt: string;
    }>;
}

interface AppleMusicExtractorInit {
    createStream?: (ext: AppleMusicExtractor, url: string, track: Track) => Promise<Readable | string>;
}
declare class AppleMusicExtractor extends BaseExtractor<AppleMusicExtractorInit> {
    static identifier: "com.discord-player.applemusicextractor";
    private _stream;
    activate(): Promise<void>;
    deactivate(): Promise<void>;
    validate(query: string, type?: SearchQueryType | null | undefined): Promise<boolean>;
    getRelatedTracks(track: Track, history: GuildQueueHistory): Promise<ExtractorInfo>;
    handle(query: string, context: ExtractorSearchContext): Promise<ExtractorInfo>;
    stream(info: Track): Promise<ExtractorStreamable>;
}

declare class AppleMusic {
    constructor();
    static search(query: string): Promise<any>;
    static getSongInfoFallback(res: HTMLElement, name: string, id: string, link: string): Promise<{
        id: string;
        duration: string;
        title: string;
        url: string;
        thumbnail: string;
        artist: {
            name: string;
        };
    } | null>;
    static getSongInfo(link: string): Promise<{
        id: any;
        duration: any;
        title: any;
        url: any;
        thumbnail: string;
        artist: {
            name: any;
        };
    } | null>;
    static getPlaylistInfo(link: string): Promise<{
        id: any;
        title: any;
        thumbnail: string;
        artist: {
            name: any;
        };
        url: any;
        tracks: any;
    } | null>;
    static getAlbumInfo(link: string): Promise<{
        id: any;
        title: any;
        thumbnail: string;
        artist: {
            name: any;
        };
        url: any;
        tracks: any;
    } | null>;
}

declare class Vimeo {
    constructor();
    /**
     * @typedef {Readable} Readable
     */
    /**
     * Downloads from vimeo
     * @param {number} id Vimeo video id
     * @returns {Promise<Readable>}
     */
    static download(id: number | string): Promise<Readable>;
    /**
     * Returns video info
     * @param {number} id Video id
     */
    static getInfo(id: number | string): Promise<VimeoInfo | null>;
}
interface VimeoInfo {
    id: number;
    duration: number;
    title: string;
    url: string;
    thumbnail: string;
    stream: string;
    author: {
        id: number;
        name: string;
        url: string;
        avatar: string;
    };
}

declare function downloadStream(url: string, opts?: RequestOptions): Promise<Readable>;

interface SP_ACCESS_TOKEN {
    token: string;
    expiresAfter: number;
    type: 'Bearer';
}
declare class SpotifyAPI {
    credentials: {
        clientId: string | null;
        clientSecret: string | null;
    };
    accessToken: SP_ACCESS_TOKEN | null;
    constructor(credentials?: {
        clientId: string | null;
        clientSecret: string | null;
    });
    get authorizationKey(): string | null;
    requestToken(): Promise<{
        token: string;
        expiresAfter: number;
        type: "Bearer";
    } | null>;
    requestAnonymousToken(): Promise<{
        token: string;
        expiresAfter: number;
        type: "Bearer";
    } | null>;
    isTokenExpired(): boolean;
    search(query: string): Promise<{
        title: string;
        duration: number;
        artist: string;
        url: string;
        thumbnail: string | null;
    }[] | null>;
    getPlaylist(id: string): Promise<{
        name: string;
        author: string;
        thumbnail: string | null;
        id: string;
        url: string;
        tracks: {
            title: string;
            duration: number;
            artist: string;
            url: string;
            thumbnail: string | null;
        }[];
    } | null>;
    getAlbum(id: string): Promise<{
        name: string;
        author: string;
        thumbnail: string | null;
        id: string;
        url: string;
        tracks: {
            title: string;
            duration: number;
            artist: string;
            url: string;
            thumbnail: string | null;
        }[];
    } | null>;
}
interface SpotifyTrack {
    album: {
        images: {
            height: number;
            url: string;
            width: number;
        }[];
    };
    artists: {
        id: string;
        name: string;
    }[];
    duration_ms: number;
    explicit: boolean;
    external_urls: {
        spotify: string;
    };
    id: string;
    name: string;
}

type index_AppleMusic = AppleMusic;
declare const index_AppleMusic: typeof AppleMusic;
type index_SpotifyAPI = SpotifyAPI;
declare const index_SpotifyAPI: typeof SpotifyAPI;
type index_SpotifyTrack = SpotifyTrack;
type index_Vimeo = Vimeo;
declare const index_Vimeo: typeof Vimeo;
type index_VimeoInfo = VimeoInfo;
declare const index_downloadStream: typeof downloadStream;
declare namespace index {
  export { index_AppleMusic as AppleMusic, index_SpotifyAPI as SpotifyAPI, type index_SpotifyTrack as SpotifyTrack, index_Vimeo as Vimeo, type index_VimeoInfo as VimeoInfo, index_downloadStream as downloadStream };
}

interface SpotifyExtractorInit {
    clientId?: string | null;
    clientSecret?: string | null;
    createStream?: (ext: SpotifyExtractor, url: string) => Promise<Readable | string>;
}
declare class SpotifyExtractor extends BaseExtractor<SpotifyExtractorInit> {
    static identifier: "com.discord-player.spotifyextractor";
    private _stream;
    private _lib;
    private _credentials;
    internal: SpotifyAPI;
    activate(): Promise<void>;
    deactivate(): Promise<void>;
    validate(query: string, type?: SearchQueryType | null | undefined): Promise<boolean>;
    getRelatedTracks(track: Track): Promise<ExtractorInfo>;
    handle(query: string, context: ExtractorSearchContext): Promise<ExtractorInfo>;
    stream(info: Track): Promise<ExtractorStreamable>;
    parse(q: string): {
        queryType: string;
        id: string;
    };
}

declare const version: string;

declare const DefaultExtractors: (typeof SoundCloudExtractor | typeof AttachmentExtractor | typeof VimeoExtractor | typeof ReverbnationExtractor | typeof AppleMusicExtractor | typeof SpotifyExtractor)[];

export { AppleMusicExtractor, type AppleMusicExtractorInit, AttachmentExtractor, DefaultExtractors, index as Internal, ReverbnationExtractor, SoundCloudExtractor, type SoundCloudExtractorInit, SpotifyExtractor, type SpotifyExtractorInit, VimeoExtractor, lyricsExtractor, version };
