package cn.tee3.manager.service;

import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
import cn.tee3.avd.AVDEngine;
import cn.tee3.avd.Device;
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.NetworkStats;
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.bean.ScheduleRoomBean;
import cn.tee3.manager.util.RxBus;
import cn.tee3.manager.view.T3VideoView;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;

public class CallbackManager implements IBaseService {

    private AVDEngineCallback avdEngineCallback;
    private RoomJoinCallback roomJoinCallback;
    private RoomCallback roomCallback;
    private MVideoCallback mVideoCallback;
    private MScreenCallback mScreenCallback;
    private MUserManagerCallback mUserManagerCallback;
    private MAudioCallback mAudioCallback;

    private AVDEngine.Listener avdEngineListener_user;
    private Room.JoinResultListener roomJoinListener_user;
    private Room.Listener roomListener_user;
    private MVideo.Listener mVideoListener_user;
    private MScreen.Listener mScreenListener_user;
    private MUserManager.Listener mUserManagerListener_user;
    private MAudio.Listener mAudioListener_user;
    private Disposable disposable;
    private boolean isRoomJoined;
    private List<User> postCallbackUserJoinNotify = new ArrayList<>();

    private CallbackManager() {
    }

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

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

    @Override
    public String init() {
        if (disposable == null) {
            RxBusMesHandlerInit();
        }
        return IBaseService.SUCCESS;
    }

    private void RxBusMesHandlerInit() {
        disposable = RxBus.getInstance().toObservable(RxBusMsgObj.class).subscribe(new Consumer<RxBusMsgObj>() {
            @Override
            public void accept(RxBusMsgObj rxBusMsgObj) {
                switch (rxBusMsgObj.getMsgTag()) {
                    case AVDManager_initCallback:
                        isRoomJoined = true;
                        if (mUserManagerListener_user != null) {
                            for (User user : postCallbackUserJoinNotify) {
                                mUserManagerListener_user.onUserJoinNotify(user);
                            }
                            postCallbackUserJoinNotify.clear();
                        }
                        break;
                }
            }
        });
    }

    public AVDEngineCallback getAvdEngineCallback() {
        if (avdEngineCallback == null) {
            avdEngineCallback = new AVDEngineCallback();
        }
        return avdEngineCallback;
    }

    public RoomJoinCallback getRoomJoinCallback() {
        if (roomJoinCallback == null) {
            roomJoinCallback = new RoomJoinCallback();
        }
        return roomJoinCallback;
    }

    public RoomCallback getRoomCallback() {
        if (roomCallback == null) {
            roomCallback = new RoomCallback();
        }
        return roomCallback;
    }

    public MVideoCallback getMVideoCallback() {
        if (mVideoCallback == null) {
            mVideoCallback = new MVideoCallback();
        }
        return mVideoCallback;
    }

    public MScreenCallback getMScreenCallback() {
        if (mScreenCallback == null) {
            mScreenCallback = new MScreenCallback();
        }
        return mScreenCallback;
    }

    public MUserManagerCallback getMUserManagerCallback() {
        if (mUserManagerCallback == null) {
            mUserManagerCallback = new MUserManagerCallback();
        }
        return mUserManagerCallback;
    }

    public MAudioCallback getMAudioCallback() {
        if (mAudioCallback == null) {
            mAudioCallback = new MAudioCallback();
        }
        return mAudioCallback;
    }

    public void setAvdEngineListener_user(AVDEngine.Listener avdEngineListener_user) {
        this.avdEngineListener_user = avdEngineListener_user;
    }

    public void setRoomJoinListener_user(Room.JoinResultListener roomJoinListener_user) {
        this.roomJoinListener_user = roomJoinListener_user;
    }

    public void setRoomListener_user(Room.Listener roomListener_user) {
        this.roomListener_user = roomListener_user;
    }

    public void setMVideoListener_user(MVideo.Listener mVideoListener_user) {
        this.mVideoListener_user = mVideoListener_user;
    }

    public void setMScreenListener_user(MScreen.Listener mScreenListener_user) {
        this.mScreenListener_user = mScreenListener_user;
    }

    public void setMUserManagerListener_user(MUserManager.Listener mUserManagerListener_user) {
        this.mUserManagerListener_user = mUserManagerListener_user;
    }

    public void setMAudioListener_user(MAudio.Listener mAudioListener_user) {
        this.mAudioListener_user = mAudioListener_user;
    }

    public void setMicrophoneListener_user(MUserManager.Listener mUserManagerListener_user) {
        this.mUserManagerListener_user = mUserManagerListener_user;
    }

    @Override
    public void dispose() {
        if (disposable != null) {
            disposable.dispose();
            disposable = null;
        }
        isRoomJoined = false;
        postCallbackUserJoinNotify.clear();

        avdEngineListener_user = null;
        roomJoinListener_user = null;
        roomListener_user = null;
        mVideoListener_user = null;
        mScreenListener_user = null;
        mUserManagerListener_user = null;
        mAudioListener_user = null;

        avdEngineCallback = null;
        roomJoinCallback = null;
        roomCallback = null;
        mVideoCallback = null;
        mScreenCallback = null;
        mUserManagerCallback = null;
        mAudioCallback = null;
    }

    public void reset() {
        isRoomJoined = false;
        postCallbackUserJoinNotify.clear();
    }

    private class AVDEngineCallback implements AVDEngine.Listener {
        @Override
        public void onInitResult(int result) {
            if (avdEngineListener_user != null) {
                avdEngineListener_user.onInitResult(result);
            }
            RxBus.getInstance().post(new RxBusMsgObj(RxBusMsgObj.MsgTag.AVDEngine_onInitResult, result));
        }

        @Override
        public void onUninitResult(int reason) {
            if (avdEngineListener_user != null) {
                avdEngineListener_user.onUninitResult(reason);
            }
        }

        @Override
        public void onGetRoomResult(int result, RoomInfo room) {
            if (avdEngineListener_user != null) {
                avdEngineListener_user.onGetRoomResult(result, room);
            }
            RxBus.getInstance().post(new RxBusMsgObj(RxBusMsgObj.MsgTag.AVDEngine_getRoom, result));
        }

        @Override
        public void onFindRoomsResult(int result, List<RoomInfo> rooms) {
            if (avdEngineListener_user != null) {
                avdEngineListener_user.onFindRoomsResult(result, rooms);
            }
        }

        @Override
        public void onScheduleRoomResult(int result, String roomId) {
            if (avdEngineListener_user != null) {
                avdEngineListener_user.onScheduleRoomResult(result, roomId);
            }
            RxBus.getInstance().post(new RxBusMsgObj(RxBusMsgObj.MsgTag.AVDEngine_onScheduleRoomResult, new ScheduleRoomBean(result, roomId)));
        }

        @Override
        public void onCancelRoomResult(int result, String roomId) {
            if (avdEngineListener_user != null) {
                avdEngineListener_user.onCancelRoomResult(result, roomId);
            }
        }

        @Override
        public void onCallOutgoingDeviceResult(int result, String userId) {
            if (avdEngineListener_user != null) {
                avdEngineListener_user.onCallOutgoingDeviceResult(result, userId);
            }
            RxBus.getInstance().post(new RxBusMsgObj(RxBusMsgObj.MsgTag.AVDEngine_onCallOutGoingDevice, result));
        }
    }

    private class RoomJoinCallback implements Room.JoinResultListener {
        @Override
        public void onJoinResult(int result) {
            if (roomJoinListener_user != null) {
                roomJoinListener_user.onJoinResult(result);
            }
            RxBus.getInstance().post(new RxBusMsgObj(RxBusMsgObj.MsgTag.Room_onJoinResult, result));
        }
    }

    private class RoomCallback implements Room.Listener {
        @Override
        public void onJoinResult(int result) {
            if (roomListener_user != null) {
                roomListener_user.onJoinResult(result);
            }
        }

        @Override
        public void onLeaveIndication(int reason, String fromId) {
            if (roomListener_user != null) {
                roomListener_user.onLeaveIndication(reason, fromId);
            }
            RxBus.getInstance().post(new RxBusMsgObj(RxBusMsgObj.MsgTag.Room_onLeaveIndication, reason));
        }

        @Override
        public void onPublicData(byte[] data, int len, String fromId) {
            if (roomListener_user != null) {
                roomListener_user.onPublicData(data, len, fromId);
            }
        }

        @Override
        public void onPrivateData(byte[] data, int len, String fromId) {
            if (roomListener_user != null) {
                roomListener_user.onPrivateData(data, len, fromId);
            }
        }

        @Override
        public void onAppDataNotify(String key, String value) {
            if (roomListener_user != null) {
                roomListener_user.onAppDataNotify(key, value);
            }
        }

        @Override
        public void onRoomStatusNotify(RoomInfo.RoomStatus status) {
            if (roomListener_user != null) {
                roomListener_user.onRoomStatusNotify(status);
            }
        }

        @Override
        public void onConnectionStatus(Room.ConnectionStatus status) {
            if (roomListener_user != null) {
                roomListener_user.onConnectionStatus(status);
            }
            RxBus.getInstance().post(new RxBusMsgObj(RxBusMsgObj.MsgTag.Room_onConnectionStatus, status));
        }

        @Override
        public void onOutgoingInviteStatusNotify(int type, String roomId, String addr, int status, String amsg) {
            if (roomListener_user != null) {
                roomListener_user.onOutgoingInviteStatusNotify(type, roomId, addr, status, amsg);
            }
        }
    }

    private class MVideoCallback implements MVideo.Listener {
        @Override
        public void onCameraStatusNotify(Device.DeviceStatus status, String fromId) {
            if (mVideoListener_user != null) {
                mVideoListener_user.onCameraStatusNotify(status, fromId);
            }
        }

        @Override
        public void onCameraDataNotify(int level, String description, String fromId) {
            if (mVideoListener_user != null) {
                mVideoListener_user.onCameraDataNotify(level, description, fromId);
            }

        }

        @Override
        public void onPublishCameraNotify(MVideo.Camera camera) {
            MeetingManager.getInstance().deviceMap.put(camera.getId(), true);
            if (mVideoListener_user != null) {
                mVideoListener_user.onPublishCameraNotify(camera);
            }
            RxBus.getInstance().post(new RxBusMsgObj(RxBusMsgObj.MsgTag.Meeting_onPublishCameraNotify, camera));
        }

        @Override
        public void onUnpublishCameraNotify(MVideo.Camera camera) {
            MeetingManager.getInstance().deviceMap.remove(camera.getId());
            if (mVideoListener_user != null) {
                mVideoListener_user.onUnpublishCameraNotify(camera);
            }
            RxBus.getInstance().post(new RxBusMsgObj(RxBusMsgObj.MsgTag.Meeting_onUnpublishCameraNotify, camera));
        }

        @Override
        public void onSubscribeResult(int result, String fromId) {
            if (mVideoListener_user != null) {
                mVideoListener_user.onSubscribeResult(result, fromId);
            }
            RxBus.getInstance().post(new RxBusMsgObj(RxBusMsgObj.MsgTag.Meeting_onSubscribeResult, new MeetingManager.CallbackParams(result, fromId)));
        }

        @Override
        public void onUnsubscribeResult(int result, String fromId) {
            if (mVideoListener_user != null) {
                mVideoListener_user.onUnsubscribeResult(result, fromId);
            }
            RxBus.getInstance().post(new RxBusMsgObj(RxBusMsgObj.MsgTag.Meeting_onUnsubscribeResult, new MeetingManager.CallbackParams(result, fromId)));
        }

        @Override
        public void onPublishLocalResult(int result, String fromId) {
            if (result == 0) {
                MeetingManager.getInstance().deviceMap.put(fromId, true);
            }
            if (mVideoListener_user != null) {
                mVideoListener_user.onPublishLocalResult(result, fromId);
            }
            RxBus.getInstance().post(new RxBusMsgObj(RxBusMsgObj.MsgTag.Meeting_onPublishLocalCameraNotify, new MeetingManager.CallbackParams(result, fromId)));
        }

        @Override
        public void onUnpublishLocalResult(int result, String fromId) {
            MeetingManager.getInstance().deviceMap.remove(fromId);
            if (mVideoListener_user != null) {
                mVideoListener_user.onUnpublishLocalResult(result, fromId);
            }
            RxBus.getInstance().post(new RxBusMsgObj(RxBusMsgObj.MsgTag.Meeting_onUnpublishLocalResult, new MeetingManager.CallbackParams(result, fromId)));
        }
    }

    private class MAudioCallback implements MAudio.Listener {
        @Override
        public void onMicrophoneStatusNotify(Device.DeviceStatus status, String fromUserId) {
            if (mAudioListener_user != null) {
                mAudioListener_user.onMicrophoneStatusNotify(status, fromUserId);
            }
        }

        @Override
        public void onAudioLevelMonitorNotify(MAudio.AudioInfo info) {
            if (mAudioListener_user != null) {
                mAudioListener_user.onAudioLevelMonitorNotify(info);
            }
            RxBus.getInstance().post(new RxBusMsgObj(RxBusMsgObj.MsgTag.Meeting_onAudioLevelMonitor, info));
        }

        @Override
        public void onOpenMicrophoneResult(int result) {
            if (mAudioListener_user != null) {
                mAudioListener_user.onOpenMicrophoneResult(result);
            }
            RxBus.getInstance().post(new RxBusMsgObj(RxBusMsgObj.MsgTag.Meeting_onOpenMicrophone, result));
        }

        @Override
        public void onCloseMicrophoneResult(int result) {
            if (mAudioListener_user != null) {
                mAudioListener_user.onCloseMicrophoneResult(result);
            }
            RxBus.getInstance().post(new RxBusMsgObj(RxBusMsgObj.MsgTag.Meeting_onCloseMicrophone, result));
        }

        @Override
        public void onAudioData(String userId, long timestamp, int sampleRate, int channels, byte[] data, int len) {
            if (mAudioListener_user != null) {
                mAudioListener_user.onAudioData(userId, timestamp, sampleRate, channels, data, len);
            }
        }

        @Override
        public void onMediaPlayNotify(String roomId, String playingMediaId, String userId, int playEvent) {
            if (mAudioListener_user != null) {
                mAudioListener_user.onMediaPlayNotify(roomId, playingMediaId, userId, playEvent);
            }
        }

        @Override
        public void onMediaPlayProgressNotify(int curMs) {
            if (mAudioListener_user != null) {
                mAudioListener_user.onMediaPlayProgressNotify(curMs);
            }
        }
    }

    private class MScreenCallback implements MScreen.Listener {
        @Override
        public void onScreenStatusNotify(Device.DeviceStatus status, String fromId) {
            if (mScreenListener_user != null) {
                mScreenListener_user.onScreenStatusNotify(status, fromId);
            }
        }

        @Override
        public void onScreenDataNotify(int level, String description, String fromId) {
            if (mScreenListener_user != null) {
                mScreenListener_user.onScreenDataNotify(level, description, fromId);
            }
        }

        @Override
        public void onPublishScreenNotify(MScreen.ScreenWindow screen) {
            MeetingManager.getInstance().deviceMap.put(screen.getId(), false);
            if (mScreenListener_user != null) {
                mScreenListener_user.onPublishScreenNotify(screen);
            }
            RxBus.getInstance().post(new RxBusMsgObj(RxBusMsgObj.MsgTag.Meeting_onPublishScreenNotify, screen));
        }

        @Override
        public void onUnpublishScreenNotify(MScreen.ScreenWindow screen) {
            MeetingManager.getInstance().deviceMap.remove(screen.getId());
            if (mScreenListener_user != null) {
                mScreenListener_user.onUnpublishScreenNotify(screen);
            }
            RxBus.getInstance().post(new RxBusMsgObj(RxBusMsgObj.MsgTag.Meeting_onUnpublishScreenNotify, screen));
        }

        @Override
        public void onSubscribeResult(int result, String fromId) {
            if (mScreenListener_user != null) {
                mScreenListener_user.onSubscribeResult(result, fromId);
            }
            RxBus.getInstance().post(new RxBusMsgObj(RxBusMsgObj.MsgTag.Meeting_onSubscribeScreenResult, new MeetingManager.CallbackParams(result, fromId)));
        }

        @Override
        public void onUnsubscribeResult(int result, String fromId) {
            if (mScreenListener_user != null) {
                mScreenListener_user.onUnsubscribeResult(result, fromId);
            }
            RxBus.getInstance().post(new RxBusMsgObj(RxBusMsgObj.MsgTag.Meeting_onUnsubscribeScreenResult, new MeetingManager.CallbackParams(result, fromId)));
        }
    }

    private class MUserManagerCallback implements MUserManager.Listener {
        @Override
        public void onUserJoinNotify(User user) {
            if (!isRoomJoined) {
                postCallbackUserJoinNotify.add(user);
                return;
            }
            if (mUserManagerListener_user != null) {
                mUserManagerListener_user.onUserJoinNotify(user);
            }
            RxBus.getInstance().post(new RxBusMsgObj(RxBusMsgObj.MsgTag.Meeting_onUserJoinNotify, user));
        }

        @Override
        public void onUserLeaveNotify(User user) {
            if (mUserManagerListener_user != null) {
                mUserManagerListener_user.onUserLeaveNotify(user);
            }
            RxBus.getInstance().post(new RxBusMsgObj(RxBusMsgObj.MsgTag.Meeting_onUserLeaveNotify, user));
        }

        @Override
        public void onUserLeaveNotify(int reason, User user) {
            if (mUserManagerListener_user != null) {
                mUserManagerListener_user.onUserLeaveNotify(reason, user);
            }
        }

        @Override
        public void onUserUpdateNotify(User user) {
            if (mUserManagerListener_user != null) {
                mUserManagerListener_user.onUserUpdateNotify(user);
            }

        }

        @Override
        public void onUserStatusNotify(int status, String fromId) {
            if (mUserManagerListener_user != null) {
                mUserManagerListener_user.onUserStatusNotify(status, fromId);
            }
        }

        @Override
        public void onUserDataNotify(String userData, String fromId) {
            if (mUserManagerListener_user != null) {
                mUserManagerListener_user.onUserDataNotify(userData, fromId);
            }
        }
    }
}
