package com.bokecc.livemodule.live;

import android.content.Context;
import android.text.TextUtils;
import android.util.Log;

import com.bokecc.dwlivedemo.BuildConfig;
import com.bokecc.dwlivedemo.DWApplication;
import com.bokecc.livemodule.live.chat.module.ChatEntity;
import com.bokecc.livemodule.utils.ThreadUtils;
import com.bokecc.sdk.mobile.live.BaseCallback;
import com.bokecc.sdk.mobile.live.DWLive;
import com.bokecc.sdk.mobile.live.DWLiveListener;
import com.bokecc.sdk.mobile.live.Exception.DWLiveException;
import com.bokecc.sdk.mobile.live.Exception.ErrorCode;
import com.bokecc.sdk.mobile.live.common.network.model.CCChatTopBean;
import com.bokecc.sdk.mobile.live.listener.LiveChangeSourceListener;
import com.bokecc.sdk.mobile.live.common.log.ELog;
import com.bokecc.sdk.mobile.live.pojo.Answer;
import com.bokecc.sdk.mobile.live.pojo.BanChatBroadcast;
import com.bokecc.sdk.mobile.live.pojo.BroadCastAction;
import com.bokecc.sdk.mobile.live.pojo.BroadCastMsg;
import com.bokecc.sdk.mobile.live.pojo.ChatMessage;
import com.bokecc.sdk.mobile.live.pojo.CoursewareInfo;
import com.bokecc.sdk.mobile.live.pojo.HDStreamQuality;
import com.bokecc.sdk.mobile.live.pojo.InteractionConfigure;
import com.bokecc.sdk.mobile.live.pojo.LiveDigestBean;
import com.bokecc.sdk.mobile.live.pojo.LiveInfo;
import com.bokecc.sdk.mobile.live.pojo.LiveLineInfo;
import com.bokecc.sdk.mobile.live.pojo.LiveQualityInfo;
import com.bokecc.sdk.mobile.live.pojo.LotteryAction;
import com.bokecc.sdk.mobile.live.pojo.PracticeInfo;
import com.bokecc.sdk.mobile.live.pojo.PracticeRankInfo;
import com.bokecc.sdk.mobile.live.pojo.PracticeStatisInfo;
import com.bokecc.sdk.mobile.live.pojo.PracticeSubmitResultInfo;
import com.bokecc.sdk.mobile.live.pojo.PrivateChatInfo;
import com.bokecc.sdk.mobile.live.pojo.Question;
import com.bokecc.sdk.mobile.live.pojo.QuestionnaireInfo;
import com.bokecc.sdk.mobile.live.pojo.QuestionnaireStatisInfo;
import com.bokecc.sdk.mobile.live.pojo.RedPacketInfo;
import com.bokecc.sdk.mobile.live.pojo.RoomInfo;
import com.bokecc.sdk.mobile.live.pojo.SettingInfo;
import com.bokecc.sdk.mobile.live.pojo.TeacherInfo;
import com.bokecc.sdk.mobile.live.pojo.UserRedminAction;
import com.bokecc.sdk.mobile.live.pojo.Viewer;
import com.bokecc.sdk.mobile.live.stream.HDLiveMediaCallRole;
import com.bokecc.sdk.mobile.live.stream.LiveStreamPlayMode;
import com.bokecc.sdk.mobile.live.stream.PullRemoteStreamCallBack;
import com.bokecc.sdk.mobile.live.stream.RemoteStreamInfo;
import com.bokecc.sdk.mobile.live.stream.StreamErrorCode;
import com.bokecc.sdk.mobile.live.stream.live.rtc.BaseRtcClient;
import com.bokecc.sdk.mobile.live.stream.RTCConnectListener;
import com.bokecc.sdk.mobile.live.stream.live.rtc.HDMediaView;
import com.bokecc.sdk.mobile.live.stream.live.rtc.RtcCallBack;
import com.bokecc.sdk.mobile.live.widget.DocView;

import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 直播相关逻辑核心处理机制
 */
public class DWLiveCoreHandler {

    private static final String TAG = DWLiveCoreHandler.class.getSimpleName();
    private static final DWLiveCoreHandler dwLiveCoreHandler = new DWLiveCoreHandler();


    /**
     * 获取DWLiveCoreHandler单例的实例
     *
     * @return dwLiveCoreHandler
     */
    public static DWLiveCoreHandler getInstance() {
        return dwLiveCoreHandler;
    }

    /**
     * 私有构造函数
     */
    private DWLiveCoreHandler() {

    }

    // region -------------------- 各类功能模块监听相关 -------------------------


    private DWLiveQAListener dwLiveQAListener;

    /**
     * 设置问答监听
     */
    public void setDwLiveQAListener(DWLiveQAListener listener) {
        dwLiveQAListener = listener;
    }

    private DWLiveChatListener dwLiveChatListener;

    /**
     * 设置聊天监听
     */
    public void setDwLiveChatListener(DWLiveChatListener listener) {
        dwLiveChatListener = listener;
    }

    private DWLiveRoomListener dwLiveRoomListener;

    /**
     * 设置直播间信息监听
     */
    public void setDwLiveRoomListener(DWLiveRoomListener dwLiveRoomListener) {
        this.dwLiveRoomListener = dwLiveRoomListener;
    }

    private DWLiveVideoListener dwLiveVideoListener;
    private DWLiveIntroListener dwLiveIntroListener;

    /**
     * 设置直播视频监听
     */
    public void setDwLiveVideoListener(DWLiveVideoListener dwLiveVideoListener) {
        this.dwLiveVideoListener = dwLiveVideoListener;
    }

    /**
     * 设置直播简介监听
     */
    public void setDwLiveIntroListener(DWLiveIntroListener dwLiveIntroListener) {
        this.dwLiveIntroListener = dwLiveIntroListener;
    }

    private DWLiveFunctionListener dwLiveFunctionListener;

    /**
     * 设置直播功能监听（签到、答题卡/投票、问卷、抽奖）
     */
    public void setDwLiveFunctionListener(DWLiveFunctionListener dwLiveFunctionListener) {
        this.dwLiveFunctionListener = dwLiveFunctionListener;
    }

    private DWLiveMoreFunctionListener dwLiveMoreFunctionListener;

    /**
     * 设置直播更多功能监听（公告、连麦、私聊）
     */
    public void setDwLiveMoreFunctionListener(DWLiveMoreFunctionListener dwLiveMoreFunctionListener) {
        this.dwLiveMoreFunctionListener = dwLiveMoreFunctionListener;
    }

    private DWLiveRTCListener dwLiveRTCListener;

    /**
     * 设置直播连麦监听 -- 用于视频和连麦画面展示
     */
    public void setDwLiveRTCListener(DWLiveRTCListener dwLiveRTCListener) {
        this.dwLiveRTCListener = dwLiveRTCListener;
    }


    private UserListener userListener;

    /**
     * 防止房间内学员退出和进入监听
     *
     * @param userListener
     */
    public void setUserListener(UserListener userListener) {
        this.userListener = userListener;
    }

    private DWLiveRedPacketListener dwLiveRedPacketListener;
    private DWLiveCoursewareListener dwLiveCoursewareListener;

    private String lastRedPacketEndId;

    public void setDwLiveRedPacketListener(DWLiveRedPacketListener dwLiveRedPacketListener) {
        this.dwLiveRedPacketListener = dwLiveRedPacketListener;
    }
    public void setDwLiveCoursewareListener(DWLiveCoursewareListener dwLiveCoursewareListener) {
        this.dwLiveCoursewareListener = dwLiveCoursewareListener;
    }

    // endregion

    // region -------------------- 设置"播放"组件/控件相关 -------------------------


    private DocView docView;


    /**
     * 设置文档展示控件
     *
     * @param docView 文档展示控件
     */
    public void setDocView(DocView docView) {
        this.docView = docView;
        DWLive dwLive = DWLive.getInstance();
        if (dwLive != null) {
            dwLive.setDWLivePlayDocView(this.docView);
        }
    }

    // endregion

    // region -------------------- 直播间模版状态相关 -------------------------

    private final static String ONLY_VIDEO_TEMPLATE_TYPE = "1";

    /**
     * 当前直播间是否有'文档'
     */
    public boolean hasPdfView() {
        DWLive dwLive = DWLive.getInstance();
        if (dwLive != null && dwLive.getTemplateInfo() != null) {
            return dwLive.getTemplateInfo().hasDoc();
        }
        return false;
    }

    /**
     * 当前直播间是否有'聊天'
     */
    public boolean hasChatView() {
        DWLive dwLive = DWLive.getInstance();
        if (dwLive != null && dwLive.getTemplateInfo() != null) {
            return dwLive.getTemplateInfo().hasChat();
        }
        return false;
    }

    /**
     * 当前直播间是否有'问答'
     */
    public boolean hasQaView() {
        DWLive dwLive = DWLive.getInstance();
        if (dwLive != null && dwLive.getTemplateInfo() != null) {
            return dwLive.getTemplateInfo().hasQa();
        }
        return false;
    }

    /**
     * 当前模版是否只有视频(大屏模式-->视频)
     * <p>
     * 注：<大屏模式-->视频>的TemplateInfo.type == 1
     *
     * @return true 为是，false为否
     */
    public boolean isOnlyVideoTemplate() {
        DWLive dwLive = DWLive.getInstance();
        if (dwLive != null && dwLive.getTemplateInfo() != null) {
            return ONLY_VIDEO_TEMPLATE_TYPE.equals(dwLive.getTemplateInfo().getType());
        }
        return false;
    }

    /**
     * 是否显示用户人数
     *
     * @return true 显示 false 不显示
     */
    public boolean isShowUserCount() {
        DWLive dwLive = DWLive.getInstance();
        if (dwLive != null && dwLive.getRoomInfo() != null) {
            return dwLive.getRoomInfo().getShowUserCount() == 1;
        }
        return false;
    }

    /**
     * 是否显示清晰度
     *
     * @return true 显示 false 不显示
     */
    public boolean isShowQuality() {
        DWLive dwLive = DWLive.getInstance();
        if (dwLive != null && dwLive.getRoomInfo() != null) {
            return (dwLive.getRoomInfo().getMultiQuality() == 1);
        }
        return false;
    }

    public boolean isVrLive() {
        LiveDigestBean liveDigestBean = DWLive.getInstance().getLiveDigestInfo();
        if (liveDigestBean != null) {
            return liveDigestBean.isVrLive();
        }
        return false;
    }

    /**
     * 是否开启跑马灯
     *
     * @return true 显示 false 不显示
     */
    public boolean isOpenMarquee() {
        DWLive dwLive = DWLive.getInstance();
        if (dwLive != null && dwLive.getRoomInfo() != null) {
            return dwLive.getRoomInfo().getOpenMarquee() == 1;
        }
        return false;
    }

    /**
     * 是否开启弹幕
     *
     * @return true 显示 false 不显示
     */
    public boolean isOpenBarrage() {
        DWLive dwLive = DWLive.getInstance();
        if (dwLive != null && dwLive.getRoomInfo() != null) {
            return dwLive.getRoomInfo().getBarrage() == 1;
        }
        return false;
    }

    /**
     * 是否开启弹幕
     *
     * @return true 显示 false 不显示
     */
    public boolean isOpenLogo() {
        DWLive dwLive = DWLive.getInstance();
        if (dwLive != null && dwLive.getRoomInfo() != null) {
            return dwLive.getRoomInfo().getBarrage() == 1;
        }
        return false;
    }

    // endregion


    // region -------------------- 直播SDK视频生命周期控制相关 -------------------------

    /**
     * 开始播放
     */
    public void start(Context context) {
        DWLive dwLive = DWLive.getInstance();
        if (dwLive != null) {
            // 设置播放参数 （回调 及 上下文）
            dwLive.setDWLivePlayParams(dwLiveListener, DWApplication.getContext());
            // 调用开始播放逻辑
            dwLive.start(context);
            // 获取随堂测统计信息
            DWLive.getInstance().getPracticeStatis("");
        }
    }

    /**
     * 停止播放
     */
    public void stop() {
        DWLive dwLive = DWLive.getInstance();
        if (dwLive != null) {
            dwLive.stop();
        }
    }

    /**
     * 释放资源
     */
    public void destroy() {
        lastRedPacketEndId = null;
        liveDataCallback = null;
        dwLiveRedPacketListener = null;
        dwLiveQAListener = null;
        dwLiveChatListener = null;
        dwLiveVideoListener = null;
        dwLiveIntroListener = null;
        dwLiveFunctionListener = null;
        dwLiveMoreFunctionListener = null;
        dwLiveRTCListener = null;
//        dwLiveRTCStatusListener = null;
//        dwLiveMultiRTCStatusListener = null;
        dwLiveRoomListener = null;
        userListener = null;
        isRtcing = false;
        isStreamError = false;
        isMultiStreamMode = false;
        if (docView != null) {
            docView = null;
        }

        DWLive dwLive = DWLive.getInstance();
        if (dwLive != null) {
            dwLive.onDestroy();
        }
    }

    /**
     * 切换清晰度
     *
     * @param quality quality
     */
    public void changeQuality(int quality, LiveChangeSourceListener changeLineCallback) {
        DWLive.getInstance().changeQuality(quality, changeLineCallback);
    }

    /**
     * 切换线路
     *
     * @param lineIndex 线路索引
     */
    public void changeLine(int lineIndex, LiveChangeSourceListener changeLineCallback) {
        DWLive.getInstance().changeLine(lineIndex, changeLineCallback);
    }

    /**
     * 切换播放模式
     *
     * @param playMode DWLive.PlayMode
     */
    public void changePlayMode(DWLive.LivePlayMode playMode, LiveChangeSourceListener changeCallBack) {
        DWLive.getInstance().changePlayMode(playMode, changeCallBack);
    }

    // 更新视频展示界面UI
    public void updatePlayModeUI(DWLive.LivePlayMode playMode) {
        if (dwLiveVideoListener != null) {
            dwLiveVideoListener.onChangePlayMode(playMode);
        }

    }

    // endregion

    // region -------------------- 直播SDK(DWLive)提供的的主动调用方法 -------------------------

    /**
     * 获取直播信息
     *
     * @return 直播信息 其中：LiveInfo.liveStartTime 为直播开始时间，LiveInfo.liveDuration "直播持续时间，单位（s），直播未开始返回-1"
     */
    public LiveInfo getLiveInfo() {
        return DWLive.getInstance().getLiveInfo();
    }

    public Viewer getViewer() {
        return DWLive.getInstance().getViewer();
    }

    public RoomInfo getRoomInfo() {
        DWLive dwLive = DWLive.getInstance();
        if (dwLive != null) {
            return dwLive.getRoomInfo();
        }
        return null;
    }

    /**
     * 获取直播场景
     * @return 0-LiveDigestBean.SCENE_BIG_CLASS,大班课   1-LiveDigestBean.SCENE_SEMINAR,研讨课
     */
    public int getLiveSceneMode(){
        if (DWLive.getInstance().getLiveDigestInfo()!=null){
            return DWLive.getInstance().getLiveDigestInfo().getLiveScene();
        }
        return 0;
    }

    /**
     * 获取直播间icon地址
     *
     * @return 直播间icon地址
     */
    public String getLiveIcon() {
        LiveDigestBean digestInfo = DWLive.getInstance().getLiveDigestInfo();
        String icon = "";
        if (digestInfo != null) {
            icon = digestInfo.getIcon();
        }
        return icon;
    }


    /**
     * 设置 vr 重力感应开关，默认开启
     *
     * @param enable true，开启重力感应，false，关闭重力感应
     */
    public void enableVrSensorControl(boolean enable) {
        DWLive.getInstance().enableVrSensorControl(enable);
    }

    /**
     * 设置 vr 分屏开关，默认关闭
     *
     * @param enable true，开启分屏，false，关闭分屏
     */
    public void enableVrSplitView(boolean enable) {
        DWLive.getInstance().enableVrSplitView(enable);
    }

    /**
     * 获取直播间是否开启 问答支持图片功能
     *
     * @return 是否开启问答支持图片
     */
    public boolean isAllowQaImageUpload() {
        LiveDigestBean digestInfo = DWLive.getInstance().getLiveDigestInfo();
        boolean isAllowQaImageUpload = false;
        if (digestInfo != null) {
            isAllowQaImageUpload = digestInfo.isAllowQaImageUpload();
        }
        return isAllowQaImageUpload;
    }

    public InteractionConfigure getInteractionConfigure() {
        return DWLive.getInstance().getInteractionConfigure();
    }

    public void getInteractionToken(BaseCallback<String> callback) {
        DWLive.getInstance().getInteractiveToken(callback);
    }

    /**
     * 发送签到信息
     */
    public void sendRollCall() {
        DWLive dwLive = DWLive.getInstance();
        if (dwLive != null) {
            dwLive.sendRollCall();
        }
    }

    private Map<String, ArrayList<Integer>> practiceResultIndexs;  // 随堂测答题结果列表

    /**
     * 发送随堂测答题结果
     *
     * @param practiceId    随堂测ID
     * @param answerOptions 随堂测回答的结果信息
     */
    public void sendPracticeAnswer(String practiceId, ArrayList<String> answerOptions) {
        DWLive dwLive = DWLive.getInstance();
        if (dwLive != null) {
            dwLive.sendPracticeAnswer(practiceId, answerOptions);
        }
    }

    // 缓存随堂测答题记录
    public void cachePracticeResult(String practiceId, ArrayList<Integer> resultIndexs) {
        if (practiceResultIndexs == null) {
            practiceResultIndexs = new HashMap<>();
        }
        practiceResultIndexs.put(practiceId, resultIndexs);
    }

    /**
     * 获取随堂测答题记录（根据随堂测ID）
     *
     * @param practiceId 随堂测ID
     */
    public ArrayList<Integer> getPracticeResult(String practiceId) {
        if (practiceResultIndexs == null) {
            return null;
        }
        return practiceResultIndexs.get(practiceId);
    }

    /**
     * 设置音量
     *
     * @param f
     */
    public void setVolume(Float f) {
        DWLive.getInstance().setVolume(f);
    }

    // endregion

    // region -------------------- 模块间UI事件处理方法(中转事件) -------------------------


    /**
     * 显示播放错误界面
     *
     * @param msg 播放错误信息
     */
    public void showError(String msg) {
        if (dwLiveRoomListener != null) {
            dwLiveRoomListener.showError(msg);
        }

    }

    // endregion
    // region -------------------- 实现直播相关功能事件监听 -------------------------


    private final DWLiveListener dwLiveListener = new DWLiveListener() {

        /**
         * 收到房间配置信息
         * @param info SettingInfo
         */
        @Override
        public void onRoomSettingInfo(SettingInfo info) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onRoomSettingInfo:" + Thread.currentThread().getName() + "," + ((info != null) ? info.toString() : ""));
                ThreadUtils.checkIsOnMainThread();
                if (liveDataCallback != null && info != null) {
                    liveDataCallback.onRoomSetting(info.getSource_type(), info.getAllow_chat(), info.getAllow_question());
                }
            }

        }

        /**
         * 后台配置切换视频文档区域
         *
         * @param isVideoMain 视频是否为主区域
         */
        @Override
        public void onSwitchVideoDoc(boolean isVideoMain) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onSwitchVideoDoc:" + Thread.currentThread().getName() + ",isVideoMain = " + isVideoMain);
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveRoomListener != null) {
                dwLiveRoomListener.onSwitchVideoDoc(isVideoMain);
            }
        }


        /**
         * 回调老师列表
         * @param infoList List<TeacherInfo>
         */
        @Override
        public void onOnlineTeachers(List<TeacherInfo> infoList) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onOnlineTeachers:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
                if (liveDataCallback != null && infoList != null && infoList.size() > 0) {
                    liveDataCallback.teacherList(infoList);
                }
            }
        }

        @Override
        public void onHistoryQuestionAnswer(List<Question> questions, List<Answer> answers) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onHistoryQuestionAnswer:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveQAListener != null) {
                dwLiveQAListener.onHistoryQuestionAnswer(questions, answers);
            }
        }

        /**
         * 提问
         *
         * @param question 问题信息
         */
        @Override
        public void onQuestion(Question question) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onQuestion:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveQAListener != null) {
                dwLiveQAListener.onQuestion(question);
            }
        }

        /**
         * 收到客户端发布的问题的编号
         *
         * @param questionId 问题id
         */
        @Override
        public void onPublishQuestion(String questionId) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onPublishQuestion:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveQAListener != null) {
                dwLiveQAListener.onPublishQuestion(questionId);
            }
        }

        /**
         * 回答
         *
         * @param answer 回答信息
         */
        @Override
        public void onAnswer(Answer answer) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onAnswer:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveQAListener != null) {
                dwLiveQAListener.onAnswer(answer);
            }
        }

        /**
         * 直播的播放状态
         *
         * @param status 包括PLAYING, PREPARING共2种状态
         */
        @Override
        public void onLiveStatus(DWLive.PlayStatus status) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onLiveStatus:" + Thread.currentThread().getName() + "," + status.toString());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveVideoListener != null) {
                dwLiveVideoListener.onLiveStatus(status);
            }
            if (dwLiveIntroListener != null) {
                dwLiveIntroListener.onLiveStatus(status);
            }
        }

        /**
         * 流结束
         *
         * @param isNormal 流是否正常结束
         * @deprecated 4.2.0，使用onLiveStop 替代
         */
        @Override
        public void onStreamEnd(boolean isNormal) {
            Log.d(TAG, "onStreamEnd:" + Thread.currentThread().getName() + ",isNormal:" + isNormal);
        }

        /**
         * 直播间结束消息（由于直播间触发鉴黄等操作导致直播间关闭的提示信息，回调用户层显示）4.2.0开始使用，替代onStreamEnd回调
         * @param isNormal 是否是正常结束
         * @param msg 消息
         * @since 4.2.0
         */
        @Override
        public void onLiveStop(boolean isNormal, String msg) {
            if (dwLiveVideoListener != null) {
                dwLiveVideoListener.onStreamEnd(isNormal);
            }
            if (dwLiveIntroListener != null) {
                dwLiveIntroListener.onStreamEnd(isNormal);
            }
            if (dwLiveRoomListener != null) {
                String reason = isNormal ? "直播已结束" : "直播等待中";
                dwLiveRoomListener.onStreamEnd(isNormal, reason);
                if (!TextUtils.isEmpty(msg)) {
                    dwLiveRoomListener.onInformation(msg);
                }
            }
            //直播结束，隐藏rtc video布局
            if (dwLiveRTCListener != null) {
                dwLiveRTCListener.onHideVideoLayout();
            }
        }

        @Override
        public void onStreamStart() {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onStreamStart:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveVideoListener != null) {
                dwLiveVideoListener.onStreamStart();
            }
            if (dwLiveIntroListener != null) {
                dwLiveIntroListener.onStreamStart();
            }
            if (dwLiveRoomListener != null) {
                dwLiveRoomListener.onStreamStart();
            }
            //如果后台配置连麦为rtc模式，直接显示videolayout
            if (dwLiveRTCListener != null && isMultiStreamMode) {
                dwLiveRTCListener.onShowVideoLayout();
            }
        }

        /**
         * 收到直播历史公聊
         *
         * @param chatLogs 补推的历史聊天信息
         */
        @Override
        public void onHistoryChatMessage(ArrayList<ChatMessage> chatLogs) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onHistoryChatMessage:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveChatListener != null) {
                dwLiveChatListener.onHistoryChatMessage(chatLogs);
            }
        }

        /**
         * 公共聊天
         *
         * @param msg 聊天信息
         */
        @Override
        public void onPublicChatMessage(ChatMessage msg) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onPublicChatMessage:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveChatListener != null) {
                dwLiveChatListener.onPublicChatMessage(msg);
            }
        }

        /**
         * 收到聊天信息状态管理事件
         *
         * @param msgStatusJson 聊天信息状态管理事件json
         */
        @Override
        public void onChatMessageStatus(String msgStatusJson) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onChatMessageStatus:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveChatListener != null) {
                dwLiveChatListener.onChatMessageStatus(msgStatusJson);
            }
        }

        @Override
        public void onChatTop(ArrayList<CCChatTopBean> ccChatTopBeanList) {
            //聊天置顶
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onChatTop:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveChatListener != null) {
                dwLiveChatListener.onChatTop(ccChatTopBeanList);
            }
        }

        @Override
        public void onUnChatTop(ArrayList<String> chatIdList) {
            //取消聊天置顶
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onUnChatTop:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveChatListener != null) {
                dwLiveChatListener.onUnChatTop(chatIdList);
            }
        }

        /**
         * 禁言消息，该消息是单个用户被禁言情况下发送消息的回调
         *
         * @param msg 聊天信息
         */
        @Override
        public void onSilenceUserChatMessage(ChatMessage msg) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onSilenceUserChatMessage:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveChatListener != null) {
                dwLiveChatListener.onSilenceUserChatMessage(msg);
            }
        }

        /**
         * 收到禁言事件
         *
         * @param mode 禁言类型 1：个人禁言  2：全员禁言
         */
        @Override
        public void onBanChat(int mode) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onBanChat:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
                Log.d(TAG, "onBanChat:mode" + mode);
            }
            if (dwLiveChatListener != null) {
                dwLiveChatListener.onBanChat(mode);
            }
        }

        /**
         * 收到解除禁言事件
         *
         * @param mode 禁言类型 1：个人禁言  2：全员禁言
         */
        @Override
        public void onUnBanChat(int mode) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onUnBanChat:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
                Log.d(TAG, "onUnBanChat:mode" + mode);
            }
            if (dwLiveChatListener != null) {
                dwLiveChatListener.onUnBanChat(mode);
            }
        }

        @Override
        public void onBanDeleteChat(String userId) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onBanDeleteChat:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
                Log.d(TAG, "onBanDeleteChat:userId" + userId);
            }
            if (dwLiveChatListener != null) {
                dwLiveChatListener.onBanDeleteChat(userId);
            }
        }

        /**
         * 别人私聊我
         *
         */
        @Override
        public void onPrivateChat(PrivateChatInfo info) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onPrivateChat:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
        }

        /**
         * 我发出的私聊
         *
         */
        @Override
        public void onPrivateChatSelf(PrivateChatInfo info) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onPrivateChatSelf:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
        }

        /**
         * 在线人数<br/>
         * 刷新频率：15秒
         *
         * @param count 人数统计
         */
        @Override
        public void onUserCountMessage(int count) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onUserCountMessage:" + Thread.currentThread().getName() + ",userCount:" + count);
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveRoomListener != null) {
                dwLiveRoomListener.showRoomUserNum(count);
            }
            if (dwLiveIntroListener != null) {
                dwLiveIntroListener.showRoomUserNum(count);
            }
        }


        /**
         * 回调当前翻页的信息<br/>
         * 注意：<br/>
         * 白板docTotalPage一直为0，pageNum从1开始<br/>
         * 其他文档docTotalPage为正常页数，pageNum从0开始
         *
         * @param docId        文档Id
         * @param docName      文档名称
         * @param pageNum      当前页码
         * @param docTotalPage 当前文档总共的页数
         */
        @Override
        public void onPageChange(String docId, String docName, int width, int height, int pageNum, int docTotalPage) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onPageChange:" + Thread.currentThread().getName() + ",docId:" + docId + ",docName:" + docName + ",pageNum:" + pageNum + ",docTotalPage:" + docTotalPage);
                ThreadUtils.checkIsOnMainThread();
                if (liveDataCallback != null) {
                    liveDataCallback.onPageChange(docId, docName, width, height, pageNum, docTotalPage);
                }
            }

            currentDocId = docId;
            currentPageNum = pageNum;
            totalPageNum = docTotalPage;
        }

        /**
         * 通知
         *
         */
        @Override
        public void onNotification(String msg) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onNotification:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
                if (liveDataCallback != null) {
                    liveDataCallback.onMessage(msg);
                }
            }

        }

        /**
         * 切换数据源
         *
         * @param switchInfo 切换数据源信息 <br>
         * 注：<br>
         * 1. 返回数据格式为：{"source_type":"10","source_type_desc":"数据源类型：摄像头打开"} <br>
         * 2. 目前此回调只会在有文档的直播间模版下才会触发
         */
        @Override
        public void onSwitchSource(String switchInfo) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onSwitchSource:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
                if (liveDataCallback != null) {
                    liveDataCallback.onSwitchSource(switchInfo);
                }
            }
        }


        /**
         * 收到历史广播信息(目前服务端只返回最后一条历史广播)
         *
         * @param msgs 广播消息列表
         */
        @Override
        public void onHistoryBroadcastMsg(ArrayList<BroadCastMsg> msgs) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onHistoryBroadcastMsg:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveChatListener != null) {
                // 判断空
                if (msgs == null) {
                    return;
                }
                // 展示历史广播信息,这里以前是单条处理，这里修改为多条处理
                dwLiveChatListener.onHistoryBroadcastMsg(msgs);

            }
        }


        /**
         * 收到广播信息（实时）
         *
         * @param msg 广播消息 包含id
         */
        @Override
        public void onBroadcastMsg(BroadCastMsg msg) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onBroadcastMsg2:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveChatListener != null) {
                dwLiveChatListener.onBroadcastMsg(msg);
            }

        }

        /**
         * 收到广播信息操作信息
         *
         * @param action 广播消息 根据id操作广播消息
         */
        @Override
        public void onBroadcastMsgAction(BroadCastAction action) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onBroadcastMsgAction:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveChatListener != null) {
                // 执行删除操作
                if (action.getAction() == 1) {
                    dwLiveChatListener.onBroadcastMsgDel(action.getId());
                }

            }
        }

        /**
         * 信息，一般包括被禁言等
         *
         */
        @Override
        public void onInformation(String msg) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onInformation:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveRoomListener != null) {
                dwLiveRoomListener.onInformation(msg);
            }
        }

        /**
         * 异常的回调
         *
         * @param exception  DWLiveException
         */
        @Override
        public void onException(DWLiveException exception) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onException:" + Thread.currentThread().getName() + "," + exception.toString());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveFunctionListener != null) {
                if (exception.getErrorCode() == ErrorCode.GET_PLAY_URL_FAILED) {
                    dwLiveFunctionListener.onException("获取播放地址失败:" + exception.getMessage());
                    //播放器显示重试
                    showError("获取播放地址失败，请重试");
                } else if (exception.getErrorCode() == ErrorCode.GET_HISTORY_FAILED) {
                    dwLiveFunctionListener.onException("获取历史信息失败:" + exception.getMessage());
                    showError("获取历史信息失败，请重试");
                } else if (exception.getErrorCode() == ErrorCode.DOC_PAGE_INFO_FAILED) {
                    dwLiveFunctionListener.onException("文档加载失败");
                } else if (exception.getErrorCode() == ErrorCode.CONNECT_SERVICE_FAILED) {
                    dwLiveFunctionListener.onException("连接socket服务器异常:" + exception.getMessage());
                } else if (exception.getErrorCode() == ErrorCode.GET_DIGEST_INFO_FAILED) {
                    dwLiveFunctionListener.onException("获取摘要信息失败:" + exception.getMessage());
                    showError("获取摘要信息失败，请重试");
                } else if (exception.getErrorCode() == ErrorCode.ROOM_SETTING_CHANGE) {
                    //单人连麦切换成多人连麦 ，退出直播间重新登录
                    if (dwLiveRTCListener != null) {
                        dwLiveRTCListener.onRoomSettingChange(ErrorCode.ROOM_SETTING_CHANGE.getCode());
                    }
                } else if (exception.getErrorCode() == ErrorCode.STREAM_ERROR) {
                    isStreamError = true;
                    //3.18.0 多人连麦两种模式，无延时和非无延时（管理后台配置）回调此错误，代表连麦断开，服务恢复不了，必须重新登录直播才能进行下一次连麦
                    //连麦错误恢复不了 ，退出直播间重新登录，如果是7，退出Activity，如果不是，主动挂断
                    //弹出弹窗，提示  7，退出直播间，
                    if (isMultiStreamMode) {
                        if (dwLiveRTCListener != null) {
                            dwLiveRTCListener.onRoomSettingChange(ErrorCode.STREAM_ERROR.getCode());
                        }
                    } else {
                        if (dwLiveRTCListener != null) {
                            dwLiveRTCListener.onStreamError();
                        }
                    }

                } else {
                    dwLiveFunctionListener.onException("unknown error:" + exception.getMessage());
                }
            }
        }

        /**
         * 用户被踢出房间的回调
         *
         * @param type 踢出房间的类型<br>
         * 10:在允许重复登录前提下，后进入者会登录会踢出先前登录者<br>
         * 20:讲师、助教、主持人通过页面踢出按钮踢出用户
         */
        @Override
        public void onKickOut(int type) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onKickOut:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveRoomListener != null) {
                dwLiveRoomListener.onKickOut();
            }
        }

        /**
         * 回调已播放时长
         *
         * @param playedTime 已播放时长，如果未开始，则时间为-1
         */
        @Override
        public void onLivePlayedTime(int playedTime) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onLivePlayedTime:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
                if (liveDataCallback != null) {
                    liveDataCallback.onPlayTime(playedTime);
                }
            }
        }

        /**
         * 获取已播放时长请求异常
         *
         * @param exception 获取已播放时长异常
         */
        @Override
        public void onLivePlayedTimeException(Exception exception) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onLivePlayedTimeException:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
        }

        @Override
        public void onRedPacketStart(String redPacketId) {
            DWLive.getInstance().requestRedPacket(redPacketId, new BaseCallback<RedPacketInfo>() {
                @Override
                public void onError(String error) {
                }

                @Override
                public void onSuccess(RedPacketInfo msg) {
                    if (dwLiveRedPacketListener != null) {
                        dwLiveRedPacketListener.onRedPacketStart(msg);
                    }
                }
            });

        }

        @Override
        public void onRedPacketEnd(String redPacketId) {
            lastRedPacketEndId = redPacketId;
            if (dwLiveRedPacketListener != null) {
                dwLiveRedPacketListener.onRedPacketEnd(redPacketId);
            }
        }

        @Override
        public void onCoursewarePush(CoursewareInfo coursewareInfo) {
            if (dwLiveCoursewareListener!=null){
                dwLiveCoursewareListener.onCoursewareEvent(coursewareInfo);
            }
        }

        @Override
        public void onLiveStreamViewPrepared(HDMediaView hdMediaView) {
            if (dwLiveVideoListener != null) {
                dwLiveVideoListener.onLiveMediaView(hdMediaView);
            }
        }

        /**
         * 是否是时移播放
         *
         */
        @Override
        public void isPlayedBack(boolean isPlayedBack) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "isPlayedBack:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
        }


        /**
         * 定制聊天
         *
         * @param customMessage customMessage
         */
        @Override
        public void onCustomMessage(String customMessage) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onCustomMessage:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
                Log.d(TAG, "onCustomMessage:" + customMessage);
                if (liveDataCallback != null) {
                    liveDataCallback.onMessage(customMessage);
                }
            }
        }

        /**
         * 禁播
         *
         * @param reason 禁播原因
         */
        @Override
        public void onBanStream(String reason) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onBanStream:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
                Log.d(TAG, "onBanStream:reason" + reason);
            }
            if (dwLiveVideoListener != null) {
                dwLiveVideoListener.onBanStream(reason);
            }
            if (dwLiveRoomListener != null) {
                dwLiveRoomListener.onStreamEnd(true, reason);
            }
        }

        /**
         * 解禁
         */
        @Override
        public void onUnbanStream() {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onUnbanStream:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveVideoListener != null) {
                dwLiveVideoListener.onUnbanStream();
            }
        }

        @Override
        public void onInitFinished() {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onInitFinished:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveRoomListener != null && DWLive.getInstance().getRoomInfo() != null) {
                dwLiveRoomListener.showRoomTitle(DWLive.getInstance().getRoomInfo().getName());
            }
            if (dwLiveIntroListener != null && DWLive.getInstance().getRoomInfo() != null) {
                dwLiveIntroListener.showRoomTitle(DWLive.getInstance().getRoomInfo().getName());
            }
            // 获取抽奖1.0状态
            DWLive.getInstance().queryLotteryStatus();
            // 获取问卷
            DWLive.getInstance().fetchQuestionnaire();
            //获取红包雨
            DWLive.getInstance().requestRedPacket("", new BaseCallback<RedPacketInfo>() {
                @Override
                public void onError(String error) {
                }

                @Override
                public void onSuccess(RedPacketInfo msg) {
                    if (dwLiveRedPacketListener != null && msg != null) {
                        if (!TextUtils.isEmpty(lastRedPacketEndId) && lastRedPacketEndId.equals(msg.getId())) {
                            return;
                        }
                        dwLiveRedPacketListener.onRedPacketStart(msg);
                    }
                }
            });

        }

        @Override
        public void onHDAudioMode(DWLive.LiveAudio hasAudio) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onHDAudioMode:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveRoomListener != null) {
                dwLiveRoomListener.onHDAudioMode(hasAudio);
            }
        }

        @Override
        public void onHDReceivedVideoQuality(List<LiveQualityInfo> videoQuality, LiveQualityInfo currentQuality) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onHDReceivedVideoQuality:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveRoomListener != null) {
                dwLiveRoomListener.onHDReceivedVideoQuality(videoQuality, currentQuality);
            }
        }

        @Override
        public void onHDReceivedVideoAudioLines(List<LiveLineInfo> lines, int indexNum) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onHDReceivedVideoAudioLines:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveRoomListener != null) {
                dwLiveRoomListener.onHDReceivedVideoAudioLines(lines, indexNum);
            }
        }

        /**
         * 公告
         *
         * @param isRemove     是否是公告删除，如果为true，表示公告删除且announcement参数为null
         * @param announcement 公告内容
         */
        @Override
        public void onAnnouncement(boolean isRemove, String announcement) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onAnnouncement:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveMoreFunctionListener != null) {
                dwLiveMoreFunctionListener.onAnnouncement(isRemove, announcement);
            }
        }

        /**
         * 签到回调
         *
         * @param duration 签到持续时间，单位为秒
         */
        @Override
        public void onRollCall(int duration) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onRollCall:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveFunctionListener != null) {
                dwLiveFunctionListener.onRollCall(duration);
            }
        }

        /**
         * 开始抽奖
         *
         * @param lotteryId 本次抽奖的id
         */
        @Override
        public void onStartLottery(String lotteryId) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onStartLottery:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveFunctionListener != null) {
                dwLiveFunctionListener.onStartLottery(lotteryId);
            }
        }

        /**
         * 抽奖结果
         *
         * @param isWin       是否中奖，true表示中奖了
         * @param lotteryCode 中奖码
         * @param lotteryId   本次抽奖的id
         * @param winnerName  中奖者的名字
         */
        @Override
        public void onLotteryResult(boolean isWin, String lotteryCode, String lotteryId, String winnerName) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onLotteryResult:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveFunctionListener != null) {
                dwLiveFunctionListener.onLotteryResult(isWin, lotteryCode, lotteryId, winnerName);
            }
        }

        /**
         * 结束抽奖
         *
         * @param lotteryId 本次抽奖的id
         */
        @Override
        public void onStopLottery(String lotteryId) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onStopLottery:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveFunctionListener != null) {
                dwLiveFunctionListener.onStopLottery(lotteryId);
            }
        }

        /**
         * 抽奖2.0
         */
        @Override
        public void onLottery(LotteryAction lotteryAction) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onLottery:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveFunctionListener != null) {
                dwLiveFunctionListener.onLottery(lotteryAction);
            }
        }

        /**
         * 开始投票
         *
         * @param voteCount 总共的选项个数2-5
         * @param VoteType  0表示单选，1表示多选，目前只有单选
         */
        @Override
        public void onVoteStart(int voteCount, int VoteType) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onVoteStart:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveFunctionListener != null) {
                dwLiveFunctionListener.onVoteStart(voteCount, VoteType);
            }
        }

        /**
         * 结束投票
         */
        @Override
        public void onVoteStop() {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onVoteStop:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveFunctionListener != null) {
                dwLiveFunctionListener.onVoteStop();
            }
        }

        /**
         * 投票结果统计
         *
         * @param jsonObject 投票结果数据
         */
        @Override
        public void onVoteResult(JSONObject jsonObject) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onVoteResult:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveFunctionListener != null) {
                dwLiveFunctionListener.onVoteResult(jsonObject);
            }
        }

        /**
         * 收到奖品发送事件
         *
         * @param type       奖品类型: 1 奖杯 2 其他(后续扩展使用)
         * @param viewerId   观看者的id
         * @param viewerName 观看者的昵称
         */
        @Override
        public void onPrizeSend(int type, String viewerId, String viewerName) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onPrizeSend:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveFunctionListener != null) {
                dwLiveFunctionListener.onPrizeSend(type, viewerId, viewerName);
            }
        }

        /**
         * 发布问卷
         *
         * @param info 问卷内容
         */
        @Override
        public void onQuestionnairePublish(QuestionnaireInfo info) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onQuestionnairePublish:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveFunctionListener != null) {
                dwLiveFunctionListener.onQuestionnairePublish(info);
            }
        }

        /**
         * 停止问卷
         *
         * @param questionnaireId 问卷Id
         */
        @Override
        public void onQuestionnaireStop(String questionnaireId) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onQuestionnaireStop:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveFunctionListener != null) {
                dwLiveFunctionListener.onQuestionnaireStop(questionnaireId);
            }
        }

        /**
         * 问卷统计信息
         *
         */
        @Override
        public void onQuestionnaireStatis(QuestionnaireStatisInfo info) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onQuestionnaireStatis:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveFunctionListener != null) {
                dwLiveFunctionListener.onQuestionnaireStatis(info);
            }
        }

        /**
         * 发布第三方问卷
         *
         * @param title       问卷标题
         * @param externalUrl 第三方问卷链接
         */
        @Override
        public void onExeternalQuestionnairePublish(String title, String externalUrl) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onExeternalQuestionnairePublish:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveFunctionListener != null) {
                dwLiveFunctionListener.onExeternalQuestionnairePublish(title, externalUrl);
            }
        }

        /**
         * 发布随堂测
         *
         * @param info 随堂测内容
         */
        @Override
        public void onPracticePublish(PracticeInfo info) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onPracticePublish:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveFunctionListener != null) {
                dwLiveFunctionListener.onPracticePublish(info);
            }
        }

        /**
         * 收到随堂测提交结果
         *
         * @param info 随堂测结果
         */
        @Override
        public void onPracticeSubmitResult(PracticeSubmitResultInfo info) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onPracticeSubmitResult:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveFunctionListener != null) {
                dwLiveFunctionListener.onPracticeSubmitResult(info);
            }
        }

        /**
         * 收到随堂测统计信息
         *
         * @param info 随堂测排名信息
         */
        @Override
        public void onPracticStatis(PracticeStatisInfo info) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onPracticStatis:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveFunctionListener != null) {
                dwLiveFunctionListener.onPracticStatis(info);
            }
        }

        @Override
        public void onPracticRanking(PracticeRankInfo info) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onPracticRanking:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveFunctionListener != null) {
                dwLiveFunctionListener.onPracticRanking(info);
            }
        }

        /**
         * 收到停止随堂测
         *
         * @param practiceId 随堂测ID
         */
        @Override
        public void onPracticeStop(String practiceId) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onPracticeStop:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveFunctionListener != null) {
                dwLiveFunctionListener.onPracticeStop(practiceId);
            }
        }

        /**
         * 收到关闭随堂测
         *
         * @param practiceId 随堂测ID
         */
        @Override
        public void onPracticeClose(String practiceId) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onPracticeClose:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveFunctionListener != null) {
                dwLiveFunctionListener.onPracticeClose(practiceId);
            }
        }

        /**
         *    禁言通知,通知给直播间所有人某用户被禁言
         * @param banChatBroadcast
         *    userId 用户id
         *    userName 用户名
         *    userRole 用户角色
         *    userAvatar 用户头像
         *    groupId 分组id
         */
        @Override
        public void HDBanChatBroadcastWithData(BanChatBroadcast banChatBroadcast) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "HDBanChatBroadcastWithData:" + Thread.currentThread().getName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (dwLiveChatListener != null) {
                dwLiveChatListener.HDBanChatBroadcastWithData(banChatBroadcast);
            }
        }

        /**
         *  用户进出通知
         * {@link UserRedminAction.ActionType#HDUSER_IN_REMIND} 进入直播间
         * {@link UserRedminAction.ActionType#HDUSER_OUT_REMIND}   退出直播间
         *
         * @param userJoinExitAction
         *    userId 用户id
         *    userName 用户名
         *    userRole 用户角色
         *    userAvatar 用户头像
         *    groupId 分组id
         *    role 接收端列表  1-讲师；2-助教；3-主持人；4-观看端
         *    content 自定义内容
         */
        @Override
        public void HDUserRemindWithAction(UserRedminAction userJoinExitAction) {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "HDUserRemindWithAction:" + Thread.currentThread().getName() + ",userId = " + userJoinExitAction.getUserId() + ",userName=" + userJoinExitAction.getUserName());
                ThreadUtils.checkIsOnMainThread();
            }
            if (userListener != null) {
                userListener.HDUserRemindWithAction(userJoinExitAction);
            }
        }

        @Override
        public void onMediaCallModeDidChange(LiveStreamPlayMode.MODE mode) {
            if (dwLiveRTCListener != null) {
                if (mode == LiveStreamPlayMode.MODE.NO_DELAY) {//无延迟模式（rtc模式）
                    isMultiStreamMode = true;
                    //如果后台配置连麦为rtc分流模式，直接显示videolayout
                    dwLiveRTCListener.onShowVideoLayout();
                } else {
                    isMultiStreamMode = false;
                }
                dwLiveRTCListener.onPlayModeChange(mode);
            }
        }
    };

    // endregion


    // region -------------------- 直播连麦模块 -------------------------

    public void initRtc() {
        DWLive dwLive = DWLive.getInstance();
        if (dwLive != null) {
            dwLive.setRtcClientListener(rtcConnectOutListener);
        }
    }


    private boolean isAllowRtc = false;

    /**
     * 当前是否允许连麦
     */
    public boolean isAllowRtc() {
        return isAllowRtc;
    }


    private boolean isRtcing = false;//是否正在连麦，开始连麦也算
    private boolean isOnCalling = false;//是否正在麦上，连麦成功
    private boolean mIsVideoRtc = false;
    private boolean isStreamError = false;
    private boolean isMultiStreamMode = false;//角色是7，后台配置直播使用分流模式，非上麦状态也要拉取分流


    public boolean isMultiStreamMode() {
        return isMultiStreamMode;
    }

    /**
     * 当前是否正在连麦中
     */
    public boolean isRtcing() {
        return isRtcing;
    }

    /**
     * 当前是否正在麦上
     *
     * @return
     */
    public boolean isOnCalling() {
        return isOnCalling;
    }

    /**
     * 当前连麦是否是视频连麦
     *
     * @return true 是 false 否
     */
    public boolean isVideoRtc() {
        return mIsVideoRtc;
    }

    /**
     * 当前是否是多人连麦房间
     *
     * @return true 是多人连麦 false 单人连麦
     */
    public boolean isMultiRtc() {
        return DWLive.getInstance().isMultiMediaCall();
    }

    /**
     * 学员主动申请连麦
     *
     * @param videoRtc 是否为视频连麦
     */
    public void startRTCConnect(boolean videoRtc) {
        ELog.d(TAG, "[demo_bokecc.DWLiveCoreHandler.startRTCConnect]  [videoRtc=" + videoRtc + ", isAllowRtc=" + isAllowRtc + "]");
        // 判断当前是否允许连麦，如果不允许，则不继续做任何操作
        if (!isAllowRtc) {
            return;
        }
        if (isRtcing) {
            return;
        }
        if (isStreamError) {
            //直接回调错误
            if (isMultiStreamMode) {
                if (dwLiveRTCListener != null) {
                    dwLiveRTCListener.onRoomSettingChange(ErrorCode.STREAM_ERROR.getCode());
                }
            } else {
                if (dwLiveRTCListener != null) {
                    dwLiveRTCListener.onStreamError();
                }
            }
            return;
        }
        isRtcing = true;
        mIsVideoRtc = videoRtc;
        if (dwLiveRTCListener != null) {
            dwLiveRTCListener.onStartCall();
        }
        DWLive.getInstance().callInPreviewWithType(createNewRtcCallback(), videoRtc ? BaseRtcClient.RtcConnectType.AUDIOVIDEO : BaseRtcClient.RtcConnectType.AUDIO);
    }

    /**
     * 学员收到上麦邀请后，同意上麦
     */
    public void agreeRTCCall() {
        ELog.d(TAG, "[demo_bokecc.DWLiveCoreHandler.agreeRTCCall]");
        DWLive.getInstance().agreeCallInPreview(createNewRtcCallback(), isVideoRtc() ? BaseRtcClient.RtcConnectType.AUDIOVIDEO : BaseRtcClient.RtcConnectType.AUDIO);
    }

    /**
     * 学员主动挂断,主动挂断连麦,用户主动点击下麦按钮时需要关心finishClosure的返回值，退出直播间、下课等调用	hangup时不需要关心callback
     */
    public void disConnectSpeak() {
        ELog.d(TAG, "[demo_bokecc.DWLiveCoreHandler.disConnectSpeak]");
        DWLive.getInstance().hangup(new BaseCallback() {
            @Override
            public void onError(String error) {
                if (dwLiveRTCListener != null) {
                    dwLiveRTCListener.onMessageShow("挂断失败，请重试");
                }
            }

            @Override
            public void onSuccess(Object msg) {
                if (dwLiveRTCListener != null) {
                    dwLiveRTCListener.onDisconnectSpeak();
                }
                isRtcing = false;
                isOnCalling = false;
            }
        });

    }

    /**
     * 学员收到上麦邀请，拒绝上麦
     */
    public void refuseSpeak() {
        ELog.d(TAG, "[demo_bokecc.DWLiveCoreHandler.refuseSpeak]");
        DWLive.getInstance().rejectCall();
        if (dwLiveRTCListener != null) {
            dwLiveRTCListener.onDisconnectSpeak();
        }
        isRtcing = false;
    }

    /**
     * 学员主动修改连麦麦克风状态
     *
     * @param on true开启，false关闭
     */
    public void changeMicState(boolean on) {
        ELog.d(TAG, "[demo_bokecc.DWLiveCoreHandler.changeMicState]  [on=" + on + "]");
        DWLive.getInstance().setLocalAudioEnable(on);
        if (dwLiveRTCListener != null) {
            dwLiveRTCListener.onAudioStatusChange("", on, true, false);
        }
    }

    /**
     * 学员主动修改连麦摄像头状态
     *
     * @param on true开启，false关闭
     */
    public void changeCameraState(boolean on) {
        ELog.d(TAG, "[demo_bokecc.DWLiveCoreHandler.changeCameraState]  [on=" + on + "]");
        DWLive.getInstance().setLocalVideoEnable(on);
        if (dwLiveRTCListener != null) {
            dwLiveRTCListener.onVideoStatusChange("", on, true, false);
        }
    }

    /**
     * 学员主动切换摄像头，不能区分前后，默认进入是前置摄像头
     */
    public void switchCamera() {
        ELog.d(TAG, "[demo_bokecc.DWLiveCoreHandler.switchCamera]");
        DWLive.getInstance().switchLocalCamera();
    }

    /**
     * 单人连麦-取消连麦申请
     */
    public void cancelRTCConnect() {
        ELog.d(TAG, "[demo_bokecc.DWLiveCoreHandler.cancelRTCConnect]");
        DWLive.getInstance().hangup(new BaseCallback() {
            @Override
            public void onError(String error) {

            }

            @Override
            public void onSuccess(Object msg) {
                isRtcing = false;
            }
        });
    }

    /**
     * 通过id（userId）订阅流
     *
     * @param userId 用户id
     * @param role   角色 {@link HDLiveMediaCallRole}
     */
    public void pullRemoteStreamByStreamId(final String userId, final String role) {
        ELog.d(TAG, "[demo_bokecc.DWLiveCoreHandler.pullRemoteStreamByStreamId]  [userId=" + userId + ", role=" + role + "]");
        DWLive.getInstance().pullRemoteStream(userId, new PullRemoteStreamCallBack() {
            @Override
            public void onError(String error) {
                ELog.d(TAG, "[demo_bokecc.DWLiveCoreHandler.pullRemoteStreamByStreamId.onError]  [error" + error + "]");
            }

            @Override
            public void onSuccess(HDMediaView view, RemoteStreamInfo info) {
                ELog.d(TAG, "[demo_bokecc.DWLiveCoreHandler.pullRemoteStreamByStreamId.onSuccess]  [view=" + view + ", info=" + info + "]");
                if (dwLiveRTCListener != null) {
                    dwLiveRTCListener.onRemoteStreamAdded(view, userId, role, info);
                }
            }
        });
    }

    /**
     * 通过流id（userId）移除流
     *
     * @param userId 流id
     */
    public void removeRemoteStreamByStreamId(String userId) {
        ELog.d(TAG, "[demo_bokecc.DWLiveCoreHandler.removeRemoteStreamByStreamId]  [userId=" + userId + "]");
        DWLive.getInstance().removeRemoteStream(userId, null);
    }


    /**
     * 创建连麦CallBack
     *
     * @return 连麦callback
     */
    private RtcCallBack createNewRtcCallback() {
        return new RtcCallBack() {
            @Override
            public void onFail(int code) {
                ELog.d(TAG, "[demo_bokecc.DWLiveCoreHandler.RtcCallBack.onFail]  [code=" + code + "]");
                if (dwLiveRTCListener != null) {
                    dwLiveRTCListener.onStartCallFail(code);
                }
                isRtcing = false;
                isOnCalling = false;
            }

            @Override
            public void onSuccess(HDMediaView hdMediaView) {
                ELog.d(TAG, "[demo_bokecc.DWLiveCoreHandler.RtcCallBack.onSuccess]  [hdMediaView=" + hdMediaView + "]");
                isOnCalling = true;
                if (dwLiveRTCListener != null) {
                    dwLiveRTCListener.onStartCallSuccess(hdMediaView);
                }
                if (dwLiveRoomListener != null) {
                    dwLiveRoomListener.onEnterRtc();
                }
            }
        };
    }

    // endregion

    // region -------------------- 实现直播连麦功能事件监听 -------------------------

    RTCConnectListener rtcConnectOutListener = new RTCConnectListener() {

        @Override
        public void onInviteCall() {
            ELog.d(TAG, "[demo_bokecc.DWLiveCoreHandler.onInviteCall]");
            //讲师邀请上麦
            if (dwLiveRTCListener != null) {
                dwLiveRTCListener.onReceiveCall();
            }
        }

        @Override
        public void onInviteCanceled() {
            ELog.d(TAG, "[demo_bokecc.DWLiveCoreHandler.onCancelInviteCall]");
            //讲师取消邀请
            if (dwLiveRTCListener != null) {
                dwLiveRTCListener.onReceiveCancelCall();
            }
            isRtcing = false;
            isOnCalling = false;
        }

        @Override
        public void onCallWasHangup() {
            ELog.d(TAG, "[demo_bokecc.DWLiveCoreHandler.onCallWasHangUp]");
            //讲师拒绝连麦
            if (dwLiveRTCListener != null) {
                dwLiveRTCListener.onMasterBreak();
            }
            isRtcing = false;
            isOnCalling = false;
        }

        @Override
        public void onConnectionException(int code) {
            ELog.d(TAG, "[demo_bokecc.DWLiveCoreHandler.onConnectException]  [code=" + code + "]");
            //此错误抛出，连麦异常，需要视图层走挂断逻辑
            if (dwLiveRTCListener != null) {
                if (code == StreamErrorCode.RTC_DISCONNECT) {
//                    dwLiveRTCListener.onSpeakError("连麦断开",code);
                } else {
                    dwLiveRTCListener.onSpeakError("当前网络异常，无法进行连麦", code);
                }
            }
            isRtcing = false;
            isOnCalling = false;
        }

        @Override
        public void onRemoteStreamEnable(String userId, String role) {
            ELog.d(TAG, "[demo_bokecc.DWLiveCoreHandler.onRemoteStreamEnable]  [userId=" + userId + ", role=" + role + "]");
            //远端流可用。管理后台【高级选项】配置直播观看模式 为无延时直播模式 不需要申请连麦就有可能会回调此方法。
            // 标准直播与低延时直播在上麦之后，才会回调此方法
            if (dwLiveRTCListener != null) {
                dwLiveRTCListener.onRemoteStreamEnable(mIsVideoRtc, userId, role);
            }
        }

        @Override
        public void onRemoteStreamDisable(String userId) {
            ELog.d(TAG, "[demo_bokecc.DWLiveCoreHandler.onRemoteStreamDisable]  [userId=" + userId + "]");
            //远端流不可用
            if (dwLiveRTCListener != null) {
                dwLiveRTCListener.onRemoteStreamRemoved(userId);
            }
        }

        @Override
        public void onMediaCallStatusDidChange(boolean isAllowSpeak, BaseRtcClient.RtcConnectType type) {
            ELog.d(TAG, "[demo_bokecc.DWLiveCoreHandler.onMediaCallStatusDidChange]  [isAllowSpeak=" + isAllowSpeak + ", type=" + type + "]");
            //连麦服务状态改变，讲师端可开启/关闭音视频连麦，会回调此方法，在初始化直播后之后，也会回调此方法，用户动态调整当前直播间连麦状态
            //在刚进入房间时，需要监听此方法，然后判断允许连麦，再初始化连麦视图组件
            isAllowRtc = isAllowSpeak;
            isRtcing = false;
            mIsVideoRtc = BaseRtcClient.RtcConnectType.AUDIOVIDEO == type;

            if (dwLiveRTCListener != null) {
                dwLiveRTCListener.onRTCModeChanged(isAllowRtc, isMultiRtc(), mIsVideoRtc);
            }
        }

        @Override
        public void onAudioStatusDidChange(String userid, boolean isAllowAudio, boolean isSelf) {
            ELog.d(TAG, "[demo_bokecc.DWLiveCoreHandler.onAudioStatusChange]  [userid=" + userid + ", isAllowAudio=" + isAllowAudio + ", isSelf=" + isSelf + "]");
            //远端回调麦克风状态改变，包括学员自己，但学员主动触发禁用或者启用麦克风操作，不会再回调。
            if (dwLiveRTCListener != null) {
                dwLiveRTCListener.onAudioStatusChange(userid, isAllowAudio, isSelf, true);
            }
        }

        @Override
        public void onVideoStatusDidChange(String userid, boolean isAllowVideo, boolean isSelf) {
            ELog.d(TAG, "[demo_bokecc.DWLiveCoreHandler.onVideoStatusChange]  [userid=" + userid + ", isAllowVideo=" + isAllowVideo + ", isSelf=" + isSelf + "]");
            //远端回调摄像头状态改变，包括学员自己，但学员主动触发禁用或者启用摄像头操作，不会再回调。
            if (dwLiveRTCListener != null) {
                dwLiveRTCListener.onVideoStatusChange(userid, isAllowVideo, isSelf, true);
            }
        }

        @Override
        public void onPublishQuality(HDStreamQuality hdStreamQuality) {
            if (liveDataCallback != null) {
                liveDataCallback.onPublishQuality(hdStreamQuality);
            }
        }

        @Override
        public void onPlayQuality(String userId, HDStreamQuality hdStreamQuality) {
            if (liveDataCallback != null) {
                liveDataCallback.onPlayQuality(userId, hdStreamQuality);
            }
        }
    };

    // endregion

    // region -------------------- 自由翻页相关 -------------------------
    private String currentDocId;
    private int currentPageNum;
    private int totalPageNum;

    // 获取当前DocId
    public String getCurrentDocId() {
        return currentDocId;
    }

    // 获取当前翻页
    public int getCurrentPageNum() {
        return currentPageNum;
    }

    // 获取翻页总数
    public int getTotalPageNum() {
        return totalPageNum;
    }

    // endregion

    // region -------------------- 测试相关 -------------------------
    private LiveDataCallback liveDataCallback;

    public void setLiveDataCallback(LiveDataCallback liveDataCallback) {
        this.liveDataCallback = liveDataCallback;
    }


    public static final int INTERACT_GIFT = 0;
    public static final int INTERACT_VOTE = 1;
    public static final int INTERACT_QUESTIONNAIRE = 2;
    public static final int INTERACT_RED_PACKET = 3;
    public static final int INTERACT_COMMERCE = 4;
    public static final int INTERACT_INVITE = 5;
    public static final int INTERACT_LIKE = 6;

    /**
     * 获取互动组件开关
     * @param interactType INTERACT_GIFT:礼物 INTERACT_VOTE:投票 I
     *                     NTERACT_QUESTIONNAIRE:问卷 INTERACT_RED_PACKET:红包雨
     *                     INTERACT_COMMERCE:直播带货 INTERACT_INVITE:邀请卡 INTERACT_LIKE:点赞
     * @return 0，开关关闭，其他值，打开
     */
    public int getInteractSwitch(int interactType) {
        if (getInteractionConfigure() == null) {
            return 0;
        }
        if (interactType == INTERACT_GIFT) {
            if (getInteractionConfigure().getGiftConfigure()==null){
                return 0;
            }
            return getInteractionConfigure().getGiftConfigure().getGiftSwitch();
        } else if (interactType == INTERACT_LIKE) {
            return getInteractionConfigure().getLikeSwitch();
        } else if (interactType == INTERACT_VOTE) {
            return getInteractionConfigure().getVoteSwitch();
        } else if (interactType == INTERACT_INVITE) {
            return getInteractionConfigure().getInviteSwitch();
        } else if (interactType == INTERACT_QUESTIONNAIRE) {
            if (getInteractionConfigure().getQuestionnaire()==null){
                return 0;
            }
            return getInteractionConfigure().getQuestionnaire().getSwitch();
        } else if (interactType == INTERACT_RED_PACKET) {
            return getInteractionConfigure().getRedEnvelopesSwitch();
        } else if (interactType == INTERACT_COMMERCE) {
            return getInteractionConfigure().getLiveCommerce();
        }
        return 0;
    }

    public boolean hasCoursewareView() {
        LiveDigestBean liveDigestBean = DWLive.getInstance().getLiveDigestInfo();
        boolean hasCourseware = false;
        if (liveDigestBean.getCustomMenuList()!=null){
            for (int i = 0; i <liveDigestBean.getCustomMenuList().size(); i++) {
                if (liveDigestBean.getCustomMenuList().get(i).getType()==10){
                    hasCourseware = true;
                    break;
                }
            }
        }
        return hasCourseware;
    }

    // endregion
}
