import WebSocket from 'ws';
import { TypedEmitter } from 'tiny-typed-emitter';

type StreamInfoOnline = {
    CHANNEL: {
        geo_cc: string;
        geo_rc: string;
        acpt_lang: string;
        svc_lang: string;
        ISSP: number;
        RESULT: 1;
        LOWLAYTENCYBJ: number;
        VIEWPRESET: [[Object], [Object], [Object], [Object], [Object]];
        PBNO: string;
        BNO: string;
        BJID: string;
        BJNICK: string;
        BJGRADE: number;
        STNO: string;
        ISFAV: string;
        CATE: string;
        CPNO: number;
        GRADE: string;
        BTYPE: string;
        CHATNO: string;
        BPWD: 'N' | 'Y';
        TITLE: string;
        BPS: string;
        RESOLUTION: string;
        CTIP: string;
        CTPT: string;
        VBT: string;
        CTUSER: number;
        S1440P: number;
        AUTO_HASHTAGS: string[];
        CATEGORY_TAGS: string[];
        HASH_TAGS: string[];
        CHIP: string;
        CHPT: string;
        CHDOMAIN: string;
        GWIP: string;
        GWPT: string;
        STYPE: string;
        CDN: string;
        RMD: string;
        ORG: string;
        MDPT: string;
        BTIME: number;
        DH: number;
        WC: number;
        PCON: number;
        PCON_TIME: number;
        PCON_MONTH: string[];
        PCON_OBJECT: {
            tier1: SubscriptionBadge[];
            tier2: SubscriptionBadge[];
        } | null;
        FTK: string;
        BPCBANNER: boolean;
        BPCCHATPOPBANNER: boolean;
        BPCTIMEBANNER: boolean;
        BPCPOSTROLL: string;
        BPCPREROLL: string;
        MIDROLL: {
            VALUE: string;
            OFFSET_START_TIME: number;
            OFFSET_END_TIME: number;
        };
        PREROLLTAG: string;
        MIDROLLTAG: string;
        POSTROLLTAG: string;
        BJAWARD: false;
        BJAWARDWATERMARK: false;
        BJAWARDYEAR: string;
        GEM: boolean;
        GEM_LOG: boolean;
        CLEAR_MODE_CATE: string[];
        PLAYTIMINGBUFFER_DURATION: string;
        STREAMER_PLAYTIMINGBUFFER_DURATION: string;
        MAXBUFFER_DURATION: string;
        LOWBUFFER_DURATION: string;
        PLAYBACKRATEDELTA: string;
        MAXOVERSEEKDURATION: string;
    };
};
type SubscriptionBadge = {
    MONTH: number;
    FILENAME: string;
};

declare class Logger {
    name: string;
    isEnabled: boolean;
    constructor(name: string, isEnabled: boolean);
    verbose: (msg?: any, ...optionalParams: any[]) => void;
    info: (msg?: any, ...optionalParams: any[]) => void;
    warn: (msg?: any, ...optionalParams: any[]) => void;
}

declare enum ServiceCommand {
    PING = 0,// 접속 유지
    LOGIN = 1,// 로그인
    JOIN = 2,// 입장
    JOINPART_USER = 4,// 열혈팬 입장/유저 강퇴
    USER_TIMEOUT = 8,// 채금
    CHAT = 5,// 일반 채팅
    CHAT_OGQ = 109,// OGQ스티커 채팅
    OGQ_GIFT = 118,// OGQ스티커 선물
    SET_USERFLAG = 12,// 유저플래그 변경됨
    INOUT_MANAGER = 13,// 매니저 임명/해임
    SUBNICKNAME = 14,// 채팅방 닉네임 설정
    ICE1 = 19,// 얼리기
    ICE2 = 21,// 얼리기
    SLOWMODE = 23,// 저속모드
    BALLOON = 18,// 별풍선
    BALLOON_AD = 87,// 애드벌룬
    BALLOON_AD_STATION = 107,// 방송국 별풍선
    POLL = 50,// 투표
    BLOCK_WORDS_LIST = 54,// [ '', '', '' ]
    STREAM_CLOSED = 88,// 뱅종
    SUBSCRIPTION_NEW = 91,// 신규 구독
    SUBSCRIPTION = 93,// 구독 연장
    SUBSCRIPTION_GIFT = 108,// 구독권 선물
    SYSTEM_NOTICE = 58,// 별별 수다 이런거 공지
    CHANNEL_NOTICE = 104,// 채팅 공지
    MISSION = 121
}
declare enum Userflag1 {
    HOST = 2,// 방장
    FANCLUB = 5,// 팬클럽
    MANAGER1 = 6,// 매니저
    MANAGER2 = 8,// 매니저
    FEMALE = 9,// 여성
    TIMEOUT_BY_DOBAE1 = 11,// 도배 채금
    TIMEOUT_BY_DOBAE2 = 12,// 도배 채금
    TIMEOUT_BY_DOBAE3 = 24,// 도배 채금
    MOBILE = 14,// 모바일 접속
    TOPFAN = 15,// 열혈
    DM_BLCOKED = 17,// 귓속말 차단
    QUICKVIEW = 19,// 퀵뷰
    MOBILE_WEB = 23,// 모바일 웹 접속
    FOLLOWER = 28
}
declare enum Userflag2 {
    SUBSCRIPTION_TIER1 = 18,// 1티어 구독
    SUBSCRIPTION_TIER2 = 19,// 2티어 구독
    SUBSCRIPTION_TIER3 = 20
}
declare enum IceFlag {
    FANCLUB = 5,// 팬클럽
    SUPPORTER = 6,// 서포터
    TOPFAN = 7,// 열혈팬
    SUBSCRIPTION = 8,// 구독팬
    MANAGER = 9
}

declare enum ConnectedState {
    STANDBY = 0,
    CONNECTED = 1,
    JOINED = 2
}
type ConnectionInfo = {
    channelId: string;
    host: string;
    port: number;
    password: string;
};
type ChannelEmoteInfo = {
    title: string;
    tier: 1 | 2 | 3;
    pcImg: string;
    pcAltImg: string;
    mobileImg: string;
    mobileAltImg: string;
    isAnimated: boolean;
    orderNo: string;
    blackKeyword: boolean;
};
type SoopChatMessage = {
    content: string;
    parsedContent: SoopChatMessageContent[];
    emotes: Record<string, ChannelEmoteInfo>;
    channelId: string;
    userId: string;
    normalColor: string;
    language: string;
    userType: string;
    nickname: string;
    subscription: number;
    isStreamer: boolean;
    isFan: boolean;
    isTopfan: boolean;
    isManager: boolean;
    isFemale: boolean;
    color: string;
    colorDarkmode: string;
    userflag1: number;
    userflag2: number;
    stickerUrl: string;
};
type SoopChatMessageContent = SoopChatMessageContentText | SoopChatMessageContentEmote;
type SoopChatMessageContentText = {
    type: SoopChatMessageContentType.TEXT;
    body: string;
};
type SoopChatMessageContentEmote = {
    type: SoopChatMessageContentType.EMOTE;
    body: string;
};
declare enum SoopChatMessageContentType {
    TEXT = 0,
    EMOTE = 1
}
declare enum SoopBalloonType {
    NORMAL = 0,
    AD = 1,
    VOD = 2
}
type SoopBalloon = {
    type: SoopBalloonType;
    userId: string;
    nickname: string;
    count: number;
    fanClubOrder: number;
    isStation: boolean;
    imageName: string;
    ttsType: string;
};
declare enum SoopBlockType {
    TIMEOUT = 0,
    KICK = 1
}
type SoopBlock = {
    type: SoopBlockType;
    duration: number;
    userId: string;
    nickname: string;
    by: string;
};

interface SoopChatClientEvents {
    join: (channelId: string) => void;
    part: (channelId: string) => void;
    chat: (chat: SoopChatMessage) => void;
    balloon: (balloon: SoopBalloon) => void;
    block: (block: SoopBlock) => void;
}
declare class SoopChatClient extends TypedEmitter<SoopChatClientEvents> {
    protected socket: WebSocket | null;
    protected log: Logger;
    protected _connection: ConnectionInfo | null;
    protected set connection(connection: ConnectionInfo | null);
    get connection(): ConnectionInfo | null;
    protected _stream: StreamInfoOnline | null;
    protected set stream(stream: StreamInfoOnline | null);
    get stream(): StreamInfoOnline | null;
    protected _emotes: Record<string, ChannelEmoteInfo>;
    protected set emotes(emotes: Record<string, ChannelEmoteInfo>);
    get emotes(): Record<string, ChannelEmoteInfo>;
    private _connectedState;
    protected set connectedState(state: ConnectedState);
    get connectedState(): ConnectedState;
    protected loopPingPong: NodeJS.Timeout;
    protected decoder: TextDecoder;
    constructor({ logging }: {
        logging?: boolean | undefined;
    });
    protected sendPing: () => void;
    connect: (userId: string, password?: string) => Promise<void>;
    disconnect: () => void;
    /**
     * @deprecated
     */
    close: () => void;
    send: (serviceCommand: ServiceCommand, body: string) => boolean;
    protected loadEmotes: (userId: string) => Promise<void>;
    protected joinChannel: () => void;
    protected processMessage: (msg: ArrayBuffer) => void;
    protected onMsgJoin: (bodyParted: string[]) => void;
    protected onMsgJoinPartUser: (bodyParted: string[]) => void;
    protected onMsgSetUserTimeout: (bodyParted: string[]) => void;
    protected onMsgChatMsg: (bodyParted: string[]) => void;
    protected parseContent: (content: string, isSubscriber: boolean) => [SoopChatMessageContent[], Record<string, ChannelEmoteInfo>];
    protected onMsgChatOgq: (bodyParted: string[]) => void;
    protected onMsgOgqGift: (bodyParted: string[]) => void;
    protected onMsgSetUserflag: (bodyParted: string[]) => void;
    protected onMsgInoutManager: (bodyParted: string[]) => void;
    protected onMsgIce: (bodyParted: string[]) => void;
    protected onMsgSlowMode: (bodyParted: string[]) => void;
    protected onMsgBalloon: (bodyParted: string[]) => void;
    protected onMsgBalloonAd: (bodyParted: string[]) => void;
    protected onMsgBalloonAdStation: (bodyParted: string[]) => void;
    protected onMsgPoll: (bodyParted: string[]) => void;
    protected onMsgBlockWordsList: (bodyParted: string[]) => void;
    protected onMsgStreamClosed: (_: string[]) => void;
    protected onMsgNoticeSystem: (bodyParted: string[]) => void;
    protected onMsgNotice: (bodyParted: string[]) => void;
    protected onMsgSubscriptionGift: (bodyParted: string[]) => void;
    protected onMsgSubscriptionNew: (bodyParted: string[]) => void;
    protected onMsgSubscription: (bodyParted: string[]) => void;
    protected isUserflag: (flagName: Userflag1 | Userflag2, userflag: number) => boolean;
    protected isIceflag: (flagName: IceFlag, iceflag: number) => boolean;
}

export { type ChannelEmoteInfo, ConnectedState, type ConnectionInfo, type SoopBalloon, SoopBalloonType, type SoopBlock, SoopBlockType, SoopChatClient, type SoopChatMessage, type SoopChatMessageContent, type SoopChatMessageContentEmote, type SoopChatMessageContentText, SoopChatMessageContentType, type StreamInfoOnline };
