package cn.tee3.manager.service;

import android.util.Log;

import cn.tee3.avd.AVDEngine;
import cn.tee3.avd.ErrorCode;
import cn.tee3.avd.MAudio;
import cn.tee3.avd.MScreen;
import cn.tee3.avd.MUserManager;
import cn.tee3.avd.MVideo;
import cn.tee3.avd.Room;
import cn.tee3.avd.RoomInfo;
import cn.tee3.avd.Tlog;
import cn.tee3.avd.User;
import cn.tee3.manager.bean.RxBusMsgObj;
import cn.tee3.manager.util.RxBus;
import cn.tee3.manager.util.StringUtils;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;

/**
 * 房间管理类
 */
public class RoomManager implements IBaseService {

    private static RoomParams roomParams;
    private Room room;
    private Disposable disposable;
    private static final String TAG = RoomManager.class.getSimpleName();

    private RoomManager() {
    }

    public static RoomManager getInstance() {
        return RoomManager.Builder.INSTANCE;
    }

    public static RoomManager getInstance(RoomParams roomParams) {
        RoomManager.roomParams = roomParams;
        return RoomManager.Builder.INSTANCE;
    }

    private static class Builder {
        private static final RoomManager INSTANCE = new RoomManager();
    }

    /**
     * 初始化：获取房间对象、加入房间
     * @return
     */
    @Override
    public String init() {
        if (disposable == null) {
            rxBusMesHandlerInit();
        }
        AVDEngine.instance().getRoomByRoomId(roomParams.getRoomId());
        return IBaseService.SUCCESS;
    }

    /**
     * 获取房间
     * @return
     */
    public Room getRoom() {
        return room;
    }

    public void createRoom() {
        EngineConfigure.getInstance().createRoom(new RoomInfo(roomParams.getRoomId(), true, roomParams.userId), new EngineConfigure.AVDEngineCreateRoomListener() {
            @Override
            public void success(String roomId) {
                LogHelper.getInstance().appendLog("┣  ●  cn.tee3.manager.service :: RoomManager.createRoom() 创建房间 -> 成功").printLog();
                joinRoom();
            }

            @Override
            public void error(String errorCode) {
                LogHelper.getInstance().appendLog("┣  ○  cn.tee3.manager.service :: RoomManager.createRoom() 创建房间 -> 失败").printLog();
            }
        });
    }

    public void createRoom(RoomInfo roomInfo, EngineConfigure.AVDEngineCreateRoomListener listener) {
        EngineConfigure.getInstance().createRoom(roomInfo, listener);
    }

    public void joinRoom() {
        Log.d(TAG, "roomParams -> " + roomParams.toString());
        room = Room.obtain(roomParams.getRoomId());
        if (room == null) {
            RxBus.getInstance().post(new RxBusMsgObj(RxBusMsgObj.MsgTag.Room_obtainFailure, -1));
            return;
        }

        MVideo mVideo = MVideo.getVideo(room);
        MScreen mScreen = MScreen.getScreen(room);
        MAudio mAudio = MAudio.getAudio(room);
        MUserManager userManager = MUserManager.getUserManager(room);

        if (mVideo != null) {
            mVideo.setListener(CallbackManager.getInstance().getMVideoCallback());
        }
        if (mScreen != null) {
            mScreen.setListener(CallbackManager.getInstance().getMScreenCallback());
        }
        if (userManager != null) {
            userManager.setListener(CallbackManager.getInstance().getMUserManagerCallback());
        }
        if (mAudio != null) {
            mAudio.setListener(CallbackManager.getInstance().getMAudioCallback());
        }

        room.setListener(CallbackManager.getInstance().getRoomCallback());
        room.setOption(Room.Option.ro_media_use_dtls, "true");
        room.setOption(Room.Option.ro_room_rejoin_times, "-1");

        if (roomParams.audioCodecType != null) {
            room.setOption(Room.Option.ro_audio_option_codec, roomParams.getAudioCodecType().getValue());
        }

        if (!roomParams.isAudioAutoSubscribe()) {
            room.setOption(Room.Option.ro_audio_auto_subscribe, "false");
        }

        room.enableStats(true);
        String userName = StringUtils.isNotEmpty(roomParams.userName) ? roomParams.userName : StringUtils.getUUID();
        String userId = StringUtils.isNotEmpty(roomParams.userId) ? roomParams.userId : StringUtils.getUUID();  /** userId要确保唯一性，否则后加会用户会挤掉相同id用户 */
        User user = new User(userId, userName, roomParams.getUserData());
        room.join(user, "", CallbackManager.getInstance().getRoomJoinCallback());
    }

    public static RoomParams getRoomParams() {
        return roomParams;
    }

    private void rxBusMesHandlerInit() {
        disposable = RxBus.getInstance().toObservable(RxBusMsgObj.class).subscribe(new Consumer<RxBusMsgObj>() {
            @Override
            public void accept(RxBusMsgObj rxBusMsgObj) {
                switch (rxBusMsgObj.getMsgTag()) {
                    case AVDEngine_getRoom:
                        int result = (int) rxBusMsgObj.getMsgBody();
                        if (result == ErrorCode.AVD_OK) {
                            joinRoom();
                        } else {
//                            AVDManager.permissionHelper().errorCheck(result, "获取房间信息");
                            if (result == ErrorCode.Err_Network_Failure || result == ErrorCode.Err_TimeOut) {
                                AVDManager.getInstance().wakeLineAsyncTask(true);
                                break;
                            }
                            createRoom();
                        }
                        break;
                }
            }
        });
    }

    @Override
    public void dispose() {
        synchronized (RoomManager.class) {
            if (disposable != null) {
                disposable.dispose();
                disposable = null;
            }
            if (room != null) {
                Room.destoryRoom(room);
                room = null;
            }
            roomParams = null;
        }
    }

    public static class RoomParams {
        private String roomId;
        private String userName;
        private String userId;
        private String userData;
        private String userAgent;
        private AudioCodecType audioCodecType = AudioCodecType.ISAC;
        private boolean isAudioAutoSubscribe;

        public enum AudioCodecType {
            ISAC("isac"),
            OPUS("opus"),
            PCMU("pcmu");

            private String value;

            AudioCodecType(String value) {
                this.value = value;
            }

            public String getValue() {
                return value;
            }

            public void setValue(String value) {
                this.value = value;
            }
        }

        public RoomParams(String roomId) {
            this.roomId = roomId;
            this.userName = roomId;
            this.userId = roomId;
            this.isAudioAutoSubscribe = true;
        }

        public RoomParams(String roomId, String userName) {
            this.roomId = roomId;
            this.userName = userName;
            this.userId = userName;
            this.isAudioAutoSubscribe = true;
        }

        public RoomParams(String roomId, String userName, String userId) {
            this.roomId = roomId;
            this.userName = userName;
            this.userId = userId;
            this.isAudioAutoSubscribe = true;
        }

        public RoomParams(String roomId, String userName, String userId, String userData) {
            this.roomId = roomId;
            this.userName = userName;
            this.userId = userId;
            this.userData = userData;
            this.isAudioAutoSubscribe = true;
        }

        public RoomParams(String roomId, String userName, String userId, AudioCodecType audioCodecType) {
            this.roomId = roomId;
            this.userName = userName;
            this.userId = userId;
            this.audioCodecType = audioCodecType;
            this.isAudioAutoSubscribe = true;
        }

        public RoomParams(String roomId, String userName, String userId, AudioCodecType audioCodecType, boolean isAudioAutoSubscribe) {
            this.roomId = roomId;
            this.userName = userName;
            this.userId = userId;
            this.audioCodecType = audioCodecType;
            this.isAudioAutoSubscribe = isAudioAutoSubscribe;
        }

        public String getRoomId() {
            return roomId;
        }

        public void setRoomId(String roomId) {
            this.roomId = roomId;
        }

        public String getUserName() {
            return userName;
        }

        public void setUserName(String userName) {
            this.userName = userName;
        }

        public String getUserId() {
            return userId;
        }

        public void setUserId(String userId) {
            this.userId = userId;
        }

        private String getUserAgent() {
            return userAgent;
        }

        private void setUserAgent(String userAgent) {
            this.userAgent = userAgent;
        }

        public String getUserData() {
            return userData;
        }

        public void setUserData(String userData) {
            this.userData = userData;
        }

        public AudioCodecType getAudioCodecType() {
            return audioCodecType;
        }

        public void setAudioCodecType(AudioCodecType audioCodecType) {
            this.audioCodecType = audioCodecType;
        }

        public boolean isAudioAutoSubscribe() {
            return isAudioAutoSubscribe;
        }

        public void setAudioAutoSubscribe(boolean audioAutoSubscribe) {
            isAudioAutoSubscribe = audioAutoSubscribe;
        }

        @Override
        public String toString() {
            return "RoomParams{" +
                    "roomId='" + roomId + '\'' +
                    ", userName='" + userName + '\'' +
                    ", userId='" + userId + '\'' +
                    ", userData='" + userData + '\'' +
                    ", audioCodecType=" + audioCodecType +
                    ", isAudioAutoSubscribe=" + isAudioAutoSubscribe +
                    '}';
        }
    }

}
