package com.daya.live_teaching.repository;

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

import com.cooleshow.base.common.BaseApplication;
import com.cooleshow.base.data.net.BaseResponse;
import com.cooleshow.base.data.net.RetrofitClientNoToken;
import com.cooleshow.base.data.net.RetrofitFactory;
import com.cooleshow.base.rx.BaseObserver;
import com.cooleshow.base.utils.DateUtil;
import com.cooleshow.base.utils.FileUtils;
import com.cooleshow.base.utils.RequestBodyUtil;
import com.cooleshow.base.utils.SystemUtils;
import com.daya.live_teaching.api.LiveTeachingApi;
import com.daya.live_teaching.api.WhiteBoardApi;
import com.daya.live_teaching.api.retrofit.CallBackWrapper;
import com.daya.live_teaching.api.retrofit.RetrofitClient;
import com.daya.live_teaching.api.retrofit.RetrofitUtil;
import com.daya.live_teaching.common.ResultCallback;
import com.daya.live_teaching.im.IMManager;
import com.daya.live_teaching.im.message.ApplyForSpeechMessage;
import com.daya.live_teaching.im.message.AssistantTransferMessage;
import com.daya.live_teaching.im.message.ControlDeviceNotifyMessage;
import com.daya.live_teaching.im.message.DeviceStateChangedMessage;
import com.daya.live_teaching.im.message.DisplayMessage;
import com.daya.live_teaching.im.message.ExamSongDownloadStatusMessage;
import com.daya.live_teaching.im.message.MemberChangedMessage;
import com.daya.live_teaching.im.message.MusicScoreDownloadMessage;
import com.daya.live_teaching.im.message.PlayMidiMessage;
import com.daya.live_teaching.im.message.RoleChangedMessage;
import com.daya.live_teaching.im.message.SpeechResultMessage;
import com.daya.live_teaching.im.message.TicketExpiredMessage;
import com.daya.live_teaching.im.message.TurnPageMessage;
import com.daya.live_teaching.im.message.UpgradeRoleMessage;
import com.daya.live_teaching.im.message.WhiteBoardMessage;
import com.daya.live_teaching.model.ApplyForSpeechRequest;
import com.daya.live_teaching.model.ChangedUser;
import com.daya.live_teaching.model.ClassMember;
import com.daya.live_teaching.model.DeviceControlInvite;
import com.daya.live_teaching.model.DownLoadSong;
import com.daya.live_teaching.model.FileUploadBean;
import com.daya.live_teaching.model.PlayMidi;
import com.daya.live_teaching.model.Role;
import com.daya.live_teaching.model.RoleChangedUser;
import com.daya.live_teaching.model.ScreenDisplay;
import com.daya.live_teaching.model.SpeechResult;
import com.daya.live_teaching.model.StreamResource;
import com.daya.live_teaching.model.TicketExpired;
import com.daya.live_teaching.model.UpgradeRoleInvite;
import com.daya.live_teaching.model.WhiteBoard;
import com.daya.live_teaching.model.WhiteCreateBean;
import com.daya.live_teaching.rtc.RtcManager;
import com.daya.live_teaching.utils.log.SLog;

import org.json.JSONObject;

import java.io.File;
import java.lang.annotation.Retention;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.rongcloud.rtc.api.stream.RCRTCInputStream;
import cn.rongcloud.rtc.api.stream.RCRTCVideoView;
import cn.rongcloud.rtc.base.RCRTCMediaType;
import cn.rongcloud.rtc.base.RTCErrorCode;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.schedulers.Schedulers;
import io.rong.imkit.manager.UnReadMessageManager;
import io.rong.imlib.RongIMClient;
import io.rong.imlib.model.Conversation;
import io.rong.imlib.model.Message;
import io.rong.imlib.model.MessageContent;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

/**
 * 课堂数据仓库
 */
public class ClassRepository extends BaseRepository {
    private static final String PARAM_ROOM_ID = "roomId";
    private static final String PARAM_USER_ID = "userId";
    private static final String PARAM_CAMERA_ON = "cameraOn";


    public static final String PARAM_CAMERA_TYPE = "CAMERA";
    public static final String PARAM_MICROPHONE_TYPE = "MICROPHONE";
    public static final String PARAM_MUSIC_MODE_TYPE = "MUSIC_MODE";
    public static final String PARAM_HAND_UP_TYPE = "HAND_UP";
    public static final String PARAM_EXAM_SONG_TYPE = "EXAM_SONG";
    public static final String PARAM_MUSIC_SHEET_TYPE = "MUSIC_SHEET";
    public static final String PARAM_ACCOMPANIMENT_TYPE = "ACCOMPANIMENT";


    // 5 原音6 伴奏
    private static final String PARAM_DEVICE_TYPE = "deviceType";
    private static final String PARAM_SOUND_VOLUME = "soundVolume";
    private static final String MUSIC_MODE_ON = "musicModeOn";
    private static final String PARAM_MIC_ON = "microphoneOn";
    private static final String HAND_UP_ON = "handUpOn";
    private static final String MUSIC_SCORE_ON = "musicScoreOn";
    private static final String ACCOMPANIMENT_ON = "accompanimentOn";
    private static final String PARAM_USERS = "users";
    private static final String PARAM_TICKET = "ticket";
    private static final String PARAM_ROLE = "role";
    private static final String PARAM_WHITEBOARD_ID = "whiteboardId";
    private static final String EXAM_SONG_ID = "musicScoreAccompanimentId";
    private static final String PARAM_TYPE = "type";
    private static final String PARAM_URI = "uri";
    private LiveTeachingApi sealClassService;
    private LiveTeachingApi liveClassNoToken;
    private IMManager imManager;
    private HashMap<OnClassEventListener, ClassMessageReceiveListener> classEventListenerMap = new HashMap<>();

    private WhiteBoardApi whiteBoardService;

    public ClassRepository(Context context) {
        super(context);
        sealClassService = getService(LiveTeachingApi.class);
        liveClassNoToken = RetrofitClientNoToken.getInstance().getRetrofit().create(LiveTeachingApi.class);
        whiteBoardService = RetrofitFactory.Companion.getInstance().create(WhiteBoardApi.class);
        imManager = IMManager.getInstance();
    }

    public void leave(String roomId, String userId, ResultCallback<Boolean> callBack) {
        HashMap<String, Object> bodyMap = new HashMap<>();
        bodyMap.put(PARAM_ROOM_ID, roomId);
        bodyMap.put(PARAM_USER_ID, userId);
        bodyMap.put("deviceNum", (TextUtils.isEmpty(BaseApplication.Companion.getRegistrationId()) ? SystemUtils.getUniqueIdentificationCode(getContext()) : BaseApplication.Companion.getRegistrationId()));
        sealClassService.leave(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
    }


    public void kickOff(String roomId, String userId, final ResultCallback<Boolean> callBack) {

        HashMap<String, Object> bodyMap = new HashMap<>();
        bodyMap.put(PARAM_ROOM_ID, roomId);
        bodyMap.put(PARAM_USER_ID, userId);
        sealClassService.kickOff(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
    }

    public void queryNoJoinStu(String roomId, final ResultCallback<List<ClassMember>> callBack) {

        JSONObject jsonObject = new JSONObject();
        try {
            jsonObject.put("roomId", roomId);
        } catch (Exception e) {
            e.printStackTrace();
        }
        sealClassService.queryNoJoinStu(RequestBodyUtil.convertToRequestBodyJson(jsonObject.toString())).enqueue(new CallBackWrapper<List<ClassMember>>(callBack));
    }


    public void controlCamera(String roomId, String userId, boolean cameraOn, ResultCallback<Boolean> callBack) {
        HashMap<String, Object> bodyMap = new HashMap<>();
        bodyMap.put(PARAM_ROOM_ID, roomId);
        bodyMap.put(PARAM_USER_ID, userId);
        bodyMap.put(PARAM_DEVICE_TYPE, PARAM_CAMERA_TYPE);
        bodyMap.put("enable", cameraOn);
        sealClassService.deviceControl(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
    }

    public void controlVolume(String roomId, String userId, boolean cameraOn, String deviceType, String soundVolume, ResultCallback<Boolean> callBack) {
        HashMap<String, Object> bodyMap = new HashMap<>();
        bodyMap.put(PARAM_ROOM_ID, roomId);
        bodyMap.put(PARAM_USER_ID, userId);
        bodyMap.put(PARAM_SOUND_VOLUME, soundVolume);
        bodyMap.put(PARAM_DEVICE_TYPE, PARAM_MICROPHONE_TYPE);
        bodyMap.put("enable", cameraOn);
        sealClassService.deviceControl(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
    }

    public void sendImPlayMidiMessage(String userId, String roomId, boolean enable, int rate, int customType, int playVolume, ResultCallback<Boolean> callBack) {
        HashMap<String, Object> bodyMap = new HashMap<>();
        bodyMap.put(PARAM_USER_ID, userId);
        bodyMap.put("enable", enable);
        bodyMap.put("rate", rate);
        bodyMap.put("customType", customType);
        bodyMap.put("playVolume", playVolume);
        bodyMap.put(PARAM_ROOM_ID, roomId);
        bodyMap.put(PARAM_USER_ID, userId);
        sealClassService.sendImPlayMidiMessage(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));

    }


    public void controlMicrophone(String roomId, String userId, boolean microphone, ResultCallback<Boolean> callBack) {
        HashMap<String, Object> bodyMap = new HashMap<>();
        bodyMap.put(PARAM_ROOM_ID, roomId);
        bodyMap.put(PARAM_USER_ID, userId);
        bodyMap.put(PARAM_DEVICE_TYPE, PARAM_MICROPHONE_TYPE);
        bodyMap.put("enable", microphone);
        sealClassService.deviceControl(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
    }

    public void controlHandUpOn(String roomId, String userId, boolean handUpOn, ResultCallback<Boolean> callBack) {
        HashMap<String, Object> bodyMap = new HashMap<>();
        bodyMap.put(PARAM_ROOM_ID, roomId);
        bodyMap.put(PARAM_USER_ID, userId);
        bodyMap.put(PARAM_DEVICE_TYPE, PARAM_HAND_UP_TYPE);
        bodyMap.put("enable", handUpOn);
        sealClassService.deviceControl(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
    }

    public void controlMusicMode(String roomId, String userId, boolean musicModeOn, ResultCallback<Boolean> callBack) {
        HashMap<String, Object> bodyMap = new HashMap<>();
        bodyMap.put(PARAM_ROOM_ID, roomId);
        bodyMap.put(PARAM_USER_ID, userId);
        bodyMap.put(PARAM_DEVICE_TYPE, PARAM_MUSIC_MODE_TYPE);
        bodyMap.put("enable", musicModeOn);
        sealClassService.deviceControl(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));

    }

    public void batchControlCamera(String roomId, boolean cameraOn, ResultCallback<Boolean> callBack) {
        HashMap<String, Object> bodyMap = new HashMap<>();
        bodyMap.put(PARAM_ROOM_ID, roomId);
        bodyMap.put(PARAM_DEVICE_TYPE, PARAM_CAMERA_TYPE);
        bodyMap.put("enable", cameraOn);
        sealClassService.deviceBatchControl(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
    }


    public void batchControlMusicMode(String roomId, boolean musicMode, ResultCallback<Boolean> callBack) {
        HashMap<String, Object> bodyMap = new HashMap<>();
        bodyMap.put(PARAM_ROOM_ID, roomId);
        bodyMap.put(PARAM_DEVICE_TYPE, PARAM_MUSIC_MODE_TYPE);
        bodyMap.put("enable", musicMode);
        sealClassService.deviceBatchControl(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
    }

    public void batchControlMicrophone(String roomId, String userId, boolean microphone, ResultCallback<Boolean> callBack) {
        HashMap<String, Object> bodyMap = new HashMap<>();
        bodyMap.put(PARAM_ROOM_ID, roomId);
        bodyMap.put(PARAM_USER_ID, userId);
        bodyMap.put(PARAM_DEVICE_TYPE, PARAM_MICROPHONE_TYPE);
        bodyMap.put("enable", microphone);
        sealClassService.deviceBatchControl(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));

    }

    //伴奏
    public void batchControlExamSong(String roomId, String userId, String musicScoreOn, String accompanimentOn, String musicScoreAccompanimentId, String soudnValue, ResultCallback<Boolean> callBack) {
        HashMap<String, Object> bodyMap = new HashMap<>();

        bodyMap.put(PARAM_ROOM_ID, roomId);
        bodyMap.put(PARAM_USER_ID, userId);
        bodyMap.put(EXAM_SONG_ID, musicScoreAccompanimentId);
        bodyMap.put(PARAM_SOUND_VOLUME, soudnValue);
        if (TextUtils.equals("true", musicScoreOn)) {
            bodyMap.put("enable", true);
            bodyMap.put(PARAM_DEVICE_TYPE, PARAM_MUSIC_SHEET_TYPE);
        } else if (TextUtils.equals("false", musicScoreOn)) {
            bodyMap.put("enable", false);
            bodyMap.put(PARAM_DEVICE_TYPE, PARAM_MUSIC_SHEET_TYPE);
        } else if (TextUtils.equals("true", accompanimentOn)) {
            bodyMap.put("enable", true);
            bodyMap.put(PARAM_DEVICE_TYPE, PARAM_ACCOMPANIMENT_TYPE);
        } else if (TextUtils.equals("false", accompanimentOn)) {
            bodyMap.put("enable", false);
            bodyMap.put(PARAM_DEVICE_TYPE, PARAM_ACCOMPANIMENT_TYPE);
        }
        sealClassService.deviceBatchControl(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));

    }

    public void controlExamSong(String roomId, String userId, String musicScoreOn, String accompanimentOn, String musicScoreAccompanimentId, ResultCallback<Boolean> callBack) {
        HashMap<String, Object> bodyMap = new HashMap<>();
        bodyMap.put(PARAM_ROOM_ID, roomId);
        bodyMap.put(PARAM_USER_ID, userId);
        bodyMap.put(EXAM_SONG_ID, musicScoreAccompanimentId);

        if (TextUtils.equals("true", musicScoreOn)) {
            bodyMap.put("enable", true);
            bodyMap.put(PARAM_DEVICE_TYPE, PARAM_MUSIC_SHEET_TYPE);
        } else if (TextUtils.equals("false", musicScoreOn)) {
            bodyMap.put("enable", false);
            bodyMap.put(PARAM_DEVICE_TYPE, PARAM_MUSIC_SHEET_TYPE);
        } else if (TextUtils.equals("true", accompanimentOn)) {
            bodyMap.put("enable", true);
            bodyMap.put(PARAM_DEVICE_TYPE, PARAM_ACCOMPANIMENT_TYPE);
        } else if (TextUtils.equals("false", accompanimentOn)) {
            bodyMap.put("enable", false);
            bodyMap.put(PARAM_DEVICE_TYPE, PARAM_ACCOMPANIMENT_TYPE);
        }
        sealClassService.deviceControl(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
    }

    public void deviceApprove(String roomId, String deviceType, ResultCallback<Boolean> callBack) {
        HashMap<String, Object> bodyMap = new HashMap<>();
        bodyMap.put(PARAM_ROOM_ID, roomId);
        bodyMap.put(PARAM_DEVICE_TYPE, deviceType);
        sealClassService.deviceApprove(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
    }

    public void deviceReject(String roomId, String deviceType, ResultCallback<Boolean> callBack) {
        HashMap<String, Object> bodyMap = new HashMap<>();
        bodyMap.put(PARAM_ROOM_ID, roomId);
        bodyMap.put(PARAM_DEVICE_TYPE, deviceType);
        sealClassService.deviceReject(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
    }

    public void deviceSyncHandUpOn(String roomId, String userId, boolean handUpOn, ResultCallback<Boolean> callBack) {
        HashMap<String, Object> bodyMap = new HashMap<>();
        bodyMap.put(PARAM_ROOM_ID, roomId);
        bodyMap.put(PARAM_USER_ID, userId);
        bodyMap.put(PARAM_DEVICE_TYPE, PARAM_HAND_UP_TYPE);
        bodyMap.put("enable", handUpOn);
        sealClassService.deviceSync(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
    }

    public void deviceSyncMusicMode(String roomId, boolean musicModeOn, ResultCallback<Boolean> callBack) {
        HashMap<String, Object> bodyMap = new HashMap<>();
        bodyMap.put(PARAM_ROOM_ID, roomId);
        bodyMap.put(MUSIC_MODE_ON, musicModeOn);
        bodyMap.put(PARAM_DEVICE_TYPE, PARAM_MUSIC_MODE_TYPE);
        bodyMap.put("enable", musicModeOn);
        sealClassService.deviceSync(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
    }

    public void deviceSyncCamera(String roomId, boolean cameraOn, ResultCallback<Boolean> callBack) {
        HashMap<String, Object> bodyMap = new HashMap<>();
        bodyMap.put(PARAM_ROOM_ID, roomId);
        bodyMap.put(PARAM_CAMERA_ON, cameraOn);
        bodyMap.put(PARAM_DEVICE_TYPE, PARAM_CAMERA_TYPE);
        bodyMap.put("enable", cameraOn);
        sealClassService.deviceSync(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
    }

    public void deviceSyncMic(String roomId, boolean microphoneOn, ResultCallback<Boolean> callBack) {
        HashMap<String, Object> bodyMap = new HashMap<>();
        bodyMap.put(PARAM_ROOM_ID, roomId);
        bodyMap.put(PARAM_DEVICE_TYPE, PARAM_MICROPHONE_TYPE);
        bodyMap.put("enable", microphoneOn);
        sealClassService.deviceSync(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
    }

    public void deviceSyncExamSong(String roomId, boolean examSong, ResultCallback<Boolean> callBack) {
        HashMap<String, Object> bodyMap = new HashMap<>();
        bodyMap.put(PARAM_ROOM_ID, roomId);
        bodyMap.put(PARAM_DEVICE_TYPE, PARAM_MUSIC_SHEET_TYPE);
        bodyMap.put("enable", examSong);
        sealClassService.deviceSync(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
    }

    public void downgrade(String roomId, List<ChangedUser> users, ResultCallback<Boolean> callBack) {
        HashMap<String, Object> bodyMap = new HashMap<>();
        bodyMap.put(PARAM_ROOM_ID, roomId);
        bodyMap.put(PARAM_USERS, users);
        sealClassService.downgrade(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));

    }

    public void applySpeech(String roomId, ResultCallback<Boolean> callBack) {
        HashMap<String, Object> bodyMap = new HashMap<>();
        bodyMap.put(PARAM_ROOM_ID, roomId);
        sealClassService.applySpeech(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
    }


    public void approveSpeech(String roomId, String ticket, ResultCallback<Boolean> callBack) {
        HashMap<String, Object> bodyMap = new HashMap<>();
        bodyMap.put(PARAM_ROOM_ID, roomId);
        bodyMap.put(PARAM_TICKET, ticket);
        sealClassService.applyApprove(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
    }


    public void rejectSpeech(String roomId, String ticket, ResultCallback<Boolean> callBack) {
        HashMap<String, Object> bodyMap = new HashMap<>();
        bodyMap.put(PARAM_ROOM_ID, roomId);
        bodyMap.put(PARAM_TICKET, ticket);
        sealClassService.applyReject(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
    }

    public void transferRole(String roomId, String userId, ResultCallback<Boolean> callBack) {
        HashMap<String, Object> bodyMap = new HashMap<>();
        bodyMap.put(PARAM_ROOM_ID, roomId);
        bodyMap.put(PARAM_USER_ID, userId);
        sealClassService.transferRole(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
    }

    public void upgradeIntive(String roomId, String userId, int role, ResultCallback<Boolean> callBack) {
        HashMap<String, Object> bodyMap = new HashMap<>();
        bodyMap.put(PARAM_ROOM_ID, roomId);
        bodyMap.put(PARAM_USER_ID, userId);
        bodyMap.put(PARAM_ROLE, role);
        sealClassService.upgradeInvite(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
    }

    public void upgradeApprove(String roomId, String ticket, ResultCallback<Boolean> callBack) {
        HashMap<String, Object> bodyMap = new HashMap<>();
        bodyMap.put(PARAM_ROOM_ID, roomId);
        bodyMap.put(PARAM_TICKET, ticket);
        sealClassService.upgradeApprove(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
    }

    public void upgradeReject(String roomId, String ticket, ResultCallback<Boolean> callBack) {
        HashMap<String, Object> bodyMap = new HashMap<>();
        bodyMap.put(PARAM_ROOM_ID, roomId);
        bodyMap.put(PARAM_TICKET, ticket);
        sealClassService.upgradeReject(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
    }

    public void changeRole(String roomId, String userId, int role, ResultCallback<Boolean> callBack) {
        HashMap<String, Object> bodyMap = new HashMap<>();
        bodyMap.put(PARAM_ROOM_ID, roomId);
        bodyMap.put(PARAM_USER_ID, userId);
        bodyMap.put(PARAM_ROLE, role);
        sealClassService.changeRole(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<Boolean>(callBack));
    }

    /**
     * 创建白板
     *
     * @param roomId
     * @param callBack
     */
    public void createWhiteBoard(String roomId, ResultCallback<WhiteCreateBean> callBack) {
        JSONObject jsonObject = new JSONObject();
        try {
            jsonObject.put("name", "Page1");
            jsonObject.put("userNum", 0);
            jsonObject.put("courseScheduleId", roomId);
        } catch (Exception e) {
            e.printStackTrace();
        }
        whiteBoardService.hereWhiteCreat(RequestBodyUtil.convertToRequestBodyJson(jsonObject.toString()))
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeWith(new BaseObserver<WhiteCreateBean>() {
                    @Override
                    protected void onSuccess(WhiteCreateBean data) {
                        callBack.onSuccess(data);
                    }

                    @Override
                    public void onError(Throwable e) {
                        super.onError(e);
                        e.printStackTrace();
                    }
                });
    }


    /**
     * 通知学生下载伴奏
     *
     * @param roomId
     */
    public void pushDownloadexamSongMsg(String roomId, String musicScoreAccompanimentId, ResultCallback<Boolean> callBack) {
        HashMap<String, Object> bodyMap = new HashMap<>();
        bodyMap.put(PARAM_ROOM_ID, roomId);
        bodyMap.put(EXAM_SONG_ID, musicScoreAccompanimentId);
        sealClassService.pushDownloadexamSongMsg(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<>(callBack));
    }

    /**
     * 同步学生下载结果
     *
     * @param roomId
     */
    public void adjustExamSong(String roomId, String musicScoreAccompanimentId, int status, ResultCallback<Boolean> callBack) {
        HashMap<String, Object> bodyMap = new HashMap<>();
        bodyMap.put(PARAM_ROOM_ID, roomId);
        bodyMap.put(EXAM_SONG_ID, musicScoreAccompanimentId);
        bodyMap.put("status", status);
        sealClassService.adjustExamSong(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<>(callBack));
    }


    /**
     * 上传文件
     */
    public void uploadFile(String fileUrl, Callback<BaseResponse<FileUploadBean>> observer) {
        File file = new File(fileUrl);
        RequestBody requestBody = RequestBody.create(okhttp3.MediaType.parse("image/jpg"), file);
        MultipartBody.Part part = MultipartBody.Part.createFormData("file", file.getName(), requestBody);
        sealClassService.uploadFile(part).enqueue(observer);
    }

    /**
     * 课程申诉
     */
    public void addComplaints(String courseScheduleId, String url, String content, ResultCallback<Boolean> callBack) {
        whiteBoardService.addComplaints(courseScheduleId, url, content, "ALL")
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeWith(new BaseObserver<String>() {
                    @Override
                    protected void onSuccess(String data) {
                        callBack.onSuccess(true);
                    }

                    @Override
                    public void onError(Throwable e) {
                        super.onError(e);
                        callBack.onFail(-1, null);
                    }
                });
    }

    /**
     * 下载文件
     */
    public void downloadFile(String fileUrl, String filePath, String fileName, ResultCallback<Boolean> callback) {
        liveClassNoToken.downloadFileWithFixedUrl(fileUrl).enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                if (FileUtils.writeFileToSDCard(response.body(), filePath, fileName)) {
                    callback.onSuccess(true);
                } else {
                    callback.onSuccess(false);
                }
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                callback.onSuccess(false);
            }
        });
    }

    /**
     * 切换共享画布区显示内容
     *
     * @param roomId   房间Id
     * @param type     显示类型，参考{@link ScreenDisplay.Display}
     * @param userId   当显示类型为用户时，传入该用户的id
     * @param uri      当显示类型为白板时，传入白板id
     * @param callback
     */
    public void switchDisplay(String roomId, int type, String userId, String uri, ResultCallback<Boolean> callback) {
        HashMap<String, Object> bodyMap = new HashMap<>();
        bodyMap.put(PARAM_ROOM_ID, roomId);
        String typeParams;
        if (type == ScreenDisplay.Display.LECTURER.getType()) {
            typeParams = "TEACHER";
        } else if (type == ScreenDisplay.Display.WHITEBOARD.getType()) {
            typeParams = "WHITE_BOARD";
        } else if (type == ScreenDisplay.Display.SCREEN.getType()) {
            typeParams = "SCREEN";
        } else if (type == ScreenDisplay.Display.NONE.getType()) {
            typeParams = "NONE";
        } else {
            typeParams = "STUDENT";
        }
        bodyMap.put(PARAM_TYPE, typeParams);
        if (userId != null) {
            bodyMap.put(PARAM_USER_ID, userId);
        }
        if (uri != null) {
            bodyMap.put(PARAM_URI, uri);
        }
        sealClassService.switchDisplay(RetrofitUtil.createJsonRequest(bodyMap)).enqueue(new CallBackWrapper<>(callback));
    }


    public void addOnClassEventListener(String roomId, OnClassEventListener onClassEventListener) {
        if (roomId == null) {
            SLog.e(SLog.TAG_IM, "addOnClassEventListener roomId is null");
            return;
        }

        ClassMessageReceiveListener classMessageReceiveListener = new ClassMessageReceiveListener(roomId, onClassEventListener);
        classEventListenerMap.put(onClassEventListener, classMessageReceiveListener);
        imManager.addMessageReceiveListener(classMessageReceiveListener);
        imManager.addOnUnReadMessageListener(classMessageReceiveListener);
    }

    public void removeOnClassEventListener(OnClassEventListener onClassEventListener) {
        ClassMessageReceiveListener classMessageReceiveListener = classEventListenerMap.get(onClassEventListener);
        imManager.removeMessageReceiveListener(classMessageReceiveListener);
        imManager.removeOnUnReadMessageListener(classMessageReceiveListener);
    }


    /**
     * 处理 IM 自定义消息，并回调对应的{@link OnClassEventListener}事件监听
     */
    private class ClassMessageReceiveListener implements RongIMClient.OnReceiveMessageListener, UnReadMessageManager.IUnReadMessageObserver {
        private OnClassEventListener eventListener;
        private String roomId;

        ClassMessageReceiveListener(String roomId, OnClassEventListener listener) {
            this.roomId = roomId;
            eventListener = listener;
        }

        @Override
        public boolean onReceived(Message message, int left) {
            String targetId = message.getTargetId();
            if (message.getConversationType() == Conversation.ConversationType.GROUP && (roomId == null || !roomId.equals(targetId)))
                return false;
            MessageContent content = message.getContent();
            if (content instanceof MemberChangedMessage) {
                MemberChangedMessage memberChangedMessage = (MemberChangedMessage) content;
                ClassMember classMember = new ClassMember();
                // 默认设置为 true， 如果用户的摄像头和 mic 的状态改变的话， 则会通过设备变化通知消息通知
                classMember.setMicrophone(true);
                classMember.setCamera(true);
                classMember.setRole(memberChangedMessage.getRole().getValue());
                classMember.setUserId(memberChangedMessage.getUserId());
                classMember.setUserName(memberChangedMessage.getUserName());
                classMember.setHeadUrl(memberChangedMessage.getHeadUrl());
                try {
                    long timestamp = memberChangedMessage.getTimestamp();
                    String millon = DateUtil.getMillon(timestamp);
                    classMember.setJoinTime(millon);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                classMember.setHandUpOn(memberChangedMessage.isHandUpOn());
                ClassMember.PlayMidiJsonBean playMidiJsonBean = new ClassMember.PlayMidiJsonBean();
                playMidiJsonBean.setEnable(memberChangedMessage.isMetronomeSwitch());
                classMember.setPlayMidiJson(playMidiJsonBean);
                List<ClassMember.ScheduleStudentMusicScoresBean> musicScores = classMember.getScheduleStudentMusicScores();
                if (musicScores == null) {
                    musicScores = new ArrayList<>();
                }
                classMember.setScheduleStudentMusicScores(musicScores);
                eventListener.onMemberChanged(memberChangedMessage.getAction(), classMember);
                return true;
            } else if (content instanceof WhiteBoardMessage) {
                WhiteBoardMessage whiteboardMessage = (WhiteBoardMessage) content;
                WhiteBoard whiteBoard = new WhiteBoard();
                whiteBoard.setName(whiteboardMessage.getWhiteboardName());
                whiteBoard.setWhiteboardId(whiteboardMessage.getWhiteboardId());
                eventListener.onWhiteBoardChanged(whiteboardMessage.getAction(), whiteBoard);
                return true;

            } else if (content instanceof ControlDeviceNotifyMessage) {     // 邀请开启设备消息
                ControlDeviceNotifyMessage controlDeviceNotifyMessage = (ControlDeviceNotifyMessage) content;
                DeviceControlInvite deviceControlInvite = new DeviceControlInvite();
                deviceControlInvite.setTicket(controlDeviceNotifyMessage.getTicket());
                deviceControlInvite.setAction(controlDeviceNotifyMessage.getAction());
                deviceControlInvite.setDeviceType(controlDeviceNotifyMessage.getType());
                deviceControlInvite.setOpUserId(controlDeviceNotifyMessage.getOpUserId());
                deviceControlInvite.setOpUserName(controlDeviceNotifyMessage.getOpUserName());
                eventListener.onOpenDeviceInvite(deviceControlInvite);
                return true;

            } else if (content instanceof DeviceStateChangedMessage) {    // 设备状态改变消息

                DeviceStateChangedMessage deviceStateChangedMessage = (DeviceStateChangedMessage) content;
                eventListener.onDeviceStateChanged(
                        deviceStateChangedMessage.getUserId()
                        , deviceStateChangedMessage.getType()
                        , deviceStateChangedMessage.getEnable()
                        , deviceStateChangedMessage.getMusicScoreAccompanimentId());
                eventListener.onDeviceStateChanged(
                        message.getSenderUserId(),
                        deviceStateChangedMessage.getUserId()
                        , deviceStateChangedMessage.getType()
                        , deviceStateChangedMessage.getEnable()
                        , deviceStateChangedMessage.getMusicScoreAccompanimentId());
                eventListener.onDeviceStateChanged(deviceStateChangedMessage.getSoundVolume(),
                        deviceStateChangedMessage.getType(), deviceStateChangedMessage.getMusicScoreAccompanimentId());
                return true;
            } else if (content instanceof DisplayMessage) {      // 共享画布区内容发生改变
                DisplayMessage displayMessage = (DisplayMessage) content;
                eventListener.onDisplayChanged(displayMessage.getDisplay());
                return true;
            } else if (content instanceof TurnPageMessage) {      // 白板翻页消息
                TurnPageMessage turnPageMessage = (TurnPageMessage) content;
                eventListener.onWhiteBoardPageChanged(turnPageMessage.getWhiteboardId(), turnPageMessage.getCurPg(), turnPageMessage.getUserId());
                return true;
            } else if (content instanceof RoleChangedMessage) {   // 用户角色改变
                RoleChangedMessage roleChangedMessage = (RoleChangedMessage) content;
                eventListener.onRoleChanged(roleChangedMessage.getUsers(), roleChangedMessage.getOpUserId());
                return true;

            } else if (content instanceof ApplyForSpeechMessage) {    // 申请发言
                ApplyForSpeechMessage applyForSpeechMessage = (ApplyForSpeechMessage) content;
                ApplyForSpeechRequest applyForSpeechRequest = new ApplyForSpeechRequest();
                applyForSpeechRequest.setReqUserId(applyForSpeechMessage.getReqUserId());
                applyForSpeechRequest.setReqUserName(applyForSpeechMessage.getReqUserName());
                applyForSpeechRequest.setTicket(applyForSpeechMessage.getTicket());
                eventListener.onApplyForSpeechRequest(applyForSpeechRequest);
                return true;
            } else if (content instanceof TicketExpiredMessage) {     // 申请过期消息
                TicketExpiredMessage ticketExpiredMessage = (TicketExpiredMessage) content;
                TicketExpired ticketExpired = new TicketExpired();
                ticketExpired.setTicket(ticketExpiredMessage.getTicket());
                ticketExpired.setFromUserId(ticketExpiredMessage.getFromUserId());
                ticketExpired.setToUserId(ticketExpiredMessage.getToUserId());
                eventListener.onTicketExpired(ticketExpired);
                return true;
            } else if (content instanceof SpeechResultMessage) {    // 申请发言结果消息
                SpeechResultMessage speechResultMessage = (SpeechResultMessage) content;
                SpeechResult result = new SpeechResult();
                result.setOpUserId(speechResultMessage.getOpUserId());
                result.setOpUserName(speechResultMessage.getOpUserName());
                result.setReqUserId(speechResultMessage.getReqUserId());
                result.setReqUserName(speechResultMessage.getReqUserName());
                result.setAccept(speechResultMessage.isAccept());
                eventListener.onRequestSpeechResult(result);
                return true;
            } else if (content instanceof PlayMidiMessage) {      // 播放节拍器
                PlayMidiMessage playMidiMessage = (PlayMidiMessage) content;
                PlayMidi playMidi = new PlayMidi();
                playMidi.setUserId(playMidiMessage.getUserId());
                playMidi.setEnable(playMidiMessage.isEnable());
                playMidi.setCustomType(playMidiMessage.getCustomType());
                playMidi.setRate(playMidiMessage.getRate());
                playMidi.setPlayVolume(playMidiMessage.getPlayVolume());
                eventListener.onPlayMidiMessage(playMidi);
                return true;
            } else if (content instanceof MusicScoreDownloadMessage) {      // 伴奏下载
                MusicScoreDownloadMessage downloadMessage = (MusicScoreDownloadMessage) content;
                DownLoadSong song = new DownLoadSong(downloadMessage.getId(), downloadMessage.getUrl(), downloadMessage.getMp3Url());
                eventListener.onExamSongDownloadMessage(song);
                return true;
            } else if (content instanceof ExamSongDownloadStatusMessage) {      // 伴奏下载同步
                ExamSongDownloadStatusMessage downloadStatusMessage = (ExamSongDownloadStatusMessage) content;
                eventListener.onExamSongDownloadStatus(downloadStatusMessage.getStudentId(), downloadStatusMessage.getDownLoadSongStatus());
                return true;
            }

            return false;
        }

        @Override
        public void onCountChanged(int unread) {
            if (eventListener != null) {
                eventListener.onExistUnReadMessage(unread);
            }
        }
    }


    public void setOnClassVideoEventListener(OnClassVideoEventListener listener) {
        RtcManager.getInstance().setRtcCallback(new VideoCallback(listener));
    }

    public void joinRtcRoom(String roomId, ResultCallback<String> callback) {
        RtcManager.getInstance().joinRtcRoom(roomId, callback);
    }

    public void quitRtcRoom(String roomId, ResultCallback<String> callback) {
        RtcManager.getInstance().quitRtcRoom(roomId, callback);
    }

    public void startRtcChat(RCRTCVideoView view, ResultCallback<Boolean> callback) {
        RtcManager.getInstance().startRtcChat(view, callback);
    }


    public void stopRtcChat(ResultCallback<Boolean> callback) {
        RtcManager.getInstance().stopRTCChat(callback);
    }

    public void setLocalVideoEnable(boolean enable) {
        RtcManager.getInstance().setLocalVideoEnable(enable);
    }

    public void setLocalMicEnable(boolean enable) {
        RtcManager.getInstance().setLocalMicEnable(enable);
    }

    public void muteRoomVoice(boolean mute, ResultCallback<Boolean> callback) {
        RtcManager.getInstance().muteRoomVoice(mute, callback);
    }

    public void subscribeAllResource(HashMap<String, RCRTCVideoView> videoViews, ResultCallback<Boolean> callback) {
        RtcManager.getInstance().subscribeAll(videoViews, callback);
    }


    public void subscribeResource(boolean isPlayUserAudio, boolean isSimulcast, String userId, RCRTCVideoView videoView, ResultCallback<String> callback) {
        RtcManager.getInstance().subscribe(isPlayUserAudio, isSimulcast, userId, videoView, callback);
    }

    public void subscribeResource(boolean isPlayUserAudio, boolean isSimulcast, String userId, RCRTCVideoView videoView, RCRTCVideoView screenShareView, ResultCallback<String> callback) {
        RtcManager.getInstance().subscribe(isPlayUserAudio, isSimulcast, userId, videoView, screenShareView, callback);
    }

    public void unSubscribeResource(String userId, ResultCallback<String> callback) {
        RtcManager.getInstance().unSubscribe(userId, callback);
    }

    public void subscribeVideo(String userId, RCRTCVideoView videoView, ResultCallback<String> callback) {
        RtcManager.getInstance().subscribeVideo(userId, videoView, callback);
    }

    public void unSubscribeVideo(String userId, ResultCallback<String> callback) {
        RtcManager.getInstance().unSubscribeVideo(userId, callback);
    }

    public void subscribeAudio(String userId, ResultCallback<String> callback) {
        RtcManager.getInstance().subscribeAudio(userId, callback);
    }

    public void unSubscribeAudio(String userId, ResultCallback<String> callback) {
        RtcManager.getInstance().unSubscribeAudio(userId, callback);
    }

    public void enableRTCAVInputStream(String userId, boolean isEnable) {
        RtcManager.getInstance().enableRTCAVInputStream(userId, isEnable);
    }


    public void subscribeScreen(String userId, RCRTCVideoView videoView, ResultCallback<String> callback) {
        RtcManager.getInstance().subscribeScreen(userId, videoView, callback);
    }

    public void unSubscribeScreen(String userId, ResultCallback<String> callback) {
        RtcManager.getInstance().unSubscribeScreen(userId, callback);
    }


    private class VideoCallback implements RtcManager.RtcCallback {

        private OnClassVideoEventListener listener;

        public VideoCallback(OnClassVideoEventListener listener) {
            this.listener = listener;
        }


        @Override
        public void onInitialRemoteUserList(Map<String, List<RCRTCInputStream>> userInfos) {

            if (listener != null) {
                listener.onInitVideoList(getStreamResourceList(userInfos));
            }
        }

        @Override
        public void onRemoteUserPublishResource(String userId, List<RCRTCInputStream> list) {
            if (listener != null) {
                StreamResource streamResource = getPublicStreamResource(userId, list);
                listener.onAddVideoUser(streamResource);
            }
        }

        @Override
        public void onRemoteUserUnPublishResource(String userId, List<RCRTCInputStream> list) {
            if (listener != null) {
                StreamResource streamResource = getUnPublicStreamResource(userId, list);
                listener.onRemoveVideoUser(streamResource);
            }
        }

        @Override
        public void onRemoteUserAudioStreamMute(String userId, boolean mute) {

        }

        @Override
        public void onRemoteUserVideoStreamEnabled(String userId, boolean enable) {
            if (listener != null) {
                listener.onVideoEnabled(userId, enable);
            }
        }

        @Override
        public void onFail(RTCErrorCode rtcErrorCode) {

        }

        @Override
        public void onUserJoined(String userId) {

        }

        @Override
        public void onUserLeft(String userId) {
            if (listener != null) {
                listener.onRemoveVideoUser(getUnPublicStreamResource(userId, null));
            }
        }

        @Override
        public void onUserOffline(String userId) {
            if (listener != null) {
                listener.onRemoveVideoUser(getUnPublicStreamResource(userId, null));
            }

        }

        @Override
        public void onFirstFrameDraw(String userId, String tag) {
            if (listener != null) {
                listener.onFirstFrameDraw(userId, tag);
            }
        }
    }


    private List<StreamResource> getStreamResourceList(Map<String, List<RCRTCInputStream>> userInfos) {
        if (userInfos == null) {
            return null;
        }

        List<StreamResource> resources = new ArrayList<>();
        for (Map.Entry<String, List<RCRTCInputStream>> userInfo : userInfos.entrySet()) {
            resources.add(getPublicStreamResource(userInfo.getKey(), userInfo.getValue()));
        }
        return resources;
    }

    private StreamResource getPublicStreamResource(String userId, List<RCRTCInputStream> list) {
        StreamResource streamResource = new StreamResource();
        streamResource.userId = userId;
        if (list == null) {
            return streamResource;
        }
        for (RCRTCInputStream stream : list) {
            if (stream.getMediaType() == RCRTCMediaType.AUDIO) {
                streamResource.isHasAudio = true;
            } else if (stream.getMediaType() == RCRTCMediaType.VIDEO && stream.getTag().equals("screenshare")) {
                streamResource.isHasScreen = true;
            } else {
                streamResource.isHasVideo = true;
            }
        }
        return streamResource;
    }

    private StreamResource getUnPublicStreamResource(String userId, List<RCRTCInputStream> list) {
        StreamResource streamResource = new StreamResource();
        streamResource.userId = userId;
        if (list == null) {
            streamResource.isHasVideo = false;
            streamResource.isHasScreen = false;
            streamResource.isHasVideo = false;
            return streamResource;
        }
        streamResource.isHasVideo = true;
        streamResource.isHasScreen = true;
        streamResource.isHasVideo = true;
        for (RCRTCInputStream stream : list) {
            if (stream.getMediaType() == RCRTCMediaType.AUDIO) {
                streamResource.isHasAudio = false;
            } else if (stream.getMediaType() == RCRTCMediaType.VIDEO && stream.getTag().equals("screenshare")) {
                streamResource.isHasScreen = false;
            } else {
                streamResource.isHasVideo = false;
            }
        }
        return streamResource;
    }


}
