package cn.tee3.manager.service;

import android.app.Activity;
import android.content.Context;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
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.Tlog;
import cn.tee3.manager.bean.RxBusMsgObj;
import cn.tee3.manager.bean.ScheduleRoomBean;
import cn.tee3.manager.util.LineAsyncTask;
import cn.tee3.manager.util.RxBus;
import cn.tee3.manager.view.T3VideoView;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;

/**
 * AVDSDK 管理类
 */
public class AVDManager implements IBaseService {

    private static List<IBaseService> serviceList = new ArrayList<>();
    private Context context;
    private Disposable disposable;
    private RoomManager.RoomParams roomParams;
    private RequestPermissions.PermissionCode permissionCode;
    private String tag = "AVDManager";
    private AVDSetupListener setupListener;
    private boolean isAutoModule;
    private boolean isAVDInit;
    private boolean isJoinRoomComplete;
    private boolean isWorking;
    private boolean isInitFailure;
    private Setting.AVDOption setting;
    private Setting.AVDAuthentication authentication;
    private RequestPermissionsListener permissionListener;
    private InitAVDEngineListener initAVDEngineListener;
    private JoinRoomListener joinRoomListener;

    private AVDManager() {
    }

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

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

    public Context getContext() {
        return context;
    }

    /**
     * AVDSDK 鉴权，设置 服务器地址、会议凭证、会议密匙
     * @param authentication
     * @return
     */
    public AVDManager AVDAuthentication(Setting.AVDAuthentication authentication) {
        this.authentication = authentication;
        return this;
    }

    /**
     * 获取鉴权信息
     * @return 鉴权信息如果未设置则使用默认的测试服务器
     */
    public Setting.AVDAuthentication getAuthentication() {
        if (authentication == null) {
            authentication = new Setting.AVDAuthentication();
        }
        return authentication;
    }

    /**
     * 启动
     * @param context 上下文
     * @param roomParams 房间信息：房间id 和 用户名称
     * @param listener AVDSDK 初始化完成回调
     */
    public AVDManager init(Context context, RoomManager.RoomParams roomParams, AVDSetupListener listener) {
        AVDEngine.instance();   // 先加载so包才能调用native接口（打印日志文件）。
        LogHelper.getInstance().appendLog("┏ cn.tee3.manager.service :: AVDManager.init()").printLog();
        CallbackManager.getInstance().init();
        if (!isWorking && !isAVDInit) {
            serviceList.clear();
            serviceList.add(EngineConfigure.getInstance(context));
            serviceList.add(RoomManager.getInstance(roomParams));
            serviceList.add(MeetingManager.getInstance());
            isAutoModule = true;
            isWorking = true;
            isInitFailure = false;
            this.context = context;
            this.roomParams = roomParams;
            this.setupListener = listener;

            if (disposable == null) {
                RxBusMesHandlerInit();
            }
            AVDSetup();
        }
        return this;
    }

    /**
     * 初始化
     * @return
     */
    @Override
    public String init() {
        if (disposable == null) {
            RxBusMesHandlerInit();
        }
        return IBaseService.SUCCESS;
    }

    /**
     * 启动AVDSDK
     */
    private void AVDSetup() {
        LineAsyncTask.getInstance().setCompleteListener(new LineAsyncTask.TaskCompleteListener() {
            @Override
            public void complete(boolean isSuccess) {
                isWorking = false;
                if (isSuccess) {
                    isAVDInit = true;
                }
            }
        }).execute(serviceList);
    }

    /**
     * 设置AVDSDK选项
     * @param setting SDK选项
     * @return
     */
    public AVDManager setOption(Setting.AVDOption setting) {
        this.setting = setting;
        return this;
    }


    public Setting.AVDOption getSetting() {
        if (setting == null) {
            setting = new Setting.AVDOption();
        }
        return setting;
    }

    /**
     * 设置视频显示容器
     * @param videoList
     * @return
     */
    public MeetingManager setVideoRenders(List<T3VideoView> videoList) {
        if (videoList == null || videoList.isEmpty()) {
            return MeetingManager.getInstance();
        }
        MeetingManager.getInstance().setVideoRenders(videoList);
        for (T3VideoView videoView : videoList) {
            if (!videoView.isUpdatedRender()) {
                videoView.updateRender();
            }
        }
        return MeetingManager.getInstance();
    }

    public boolean isAVDSDKInit() {
        return isAVDInit;
    }

    private void wakeLineAsyncTask() {
        LineAsyncTask.getInstance().wake();
    }

    public void wakeLineAsyncTask(boolean isRunningError) {
        if (isRunningError) {
            LineAsyncTask.getInstance().wakeAndStop();
        } else {
            LineAsyncTask.getInstance().wake();
        }
    }

    public void errorCheck(int errorCode, String msg) {
        if (errorCode != ErrorCode.AVD_OK) {
            isInitFailure = true;
            isWorking = false;
            if (setupListener != null) {
                setupListener.error(msg + "失败：" + errorCode);
            }
            Log.e(tag, msg + "失败：" + errorCode);
        }
    }

    private void RxBusMesHandlerInit() {
        disposable = RxBus.getInstance().toObservable(RxBusMsgObj.class).subscribe(new Consumer<RxBusMsgObj>() {
            @Override
            public void accept(RxBusMsgObj rxBusMsgObj) {
                int result;

                switch (rxBusMsgObj.getMsgTag()) {
                    case Permission:
                        if (rxBusMsgObj.getMsgBody() != RequestPermissions.PermissionCode.GRANTED) {
                            LogHelper.getInstance().appendLog("┣  ○  动态权限申请 -> 未通过")
                                    .printLog();
                            if (permissionListener != null) {
                                permissionListener.error("权限未通过，视频会议将不可用！");
                            }
                        } else if (permissionListener != null) {
                            LogHelper.getInstance().appendLog("┣ ● 动态权限申请 -> 通过").printLog();
                            permissionListener.success();
                        }
                        break;
                    case AVDEngine_onInitResult:
                        result = (int) rxBusMsgObj.getMsgBody();
                        if (result != ErrorCode.AVD_OK) {
                            LogHelper.getInstance().appendLog("┃\n┃\t┣  ○  初始化引擎 -> 失败：" + result)
                                    .printLog();
                        } else {
                            LogHelper.getInstance().appendLog("┃\n┃\t┣  ●  初始化引擎 -> 成功").printLog();
                            Tlog.i("AVDManager", setting.toString() + "\n" + authentication.toString());
                        }

                        if (isAutoModule) {
                            wakeLineAsyncTask(result != ErrorCode.AVD_OK);
                            errorCheck(result, "初始化引擎");
                        } else if(initAVDEngineListener != null) {
                            if (result != ErrorCode.AVD_OK) {
                                initAVDEngineListener.error("初始化引擎失败：" + result);
                            } else {
                                initAVDEngineListener.success();
                            }
                        }

                        break;
                    case Room_obtainFailure:
                        result = (int) rxBusMsgObj.getMsgBody();
                        if (isAutoModule) {
                            wakeLineAsyncTask(result != ErrorCode.AVD_OK);
                            errorCheck(result, "获取房间");
                        } else if(joinRoomListener != null) {
                            if (result != ErrorCode.AVD_OK) {
                                joinRoomListener.error("获取房间失败：" + result);
                            } else {
                                joinRoomListener.success();
                            }
                        }

                        if (result != ErrorCode.AVD_OK) {
                            LogHelper.getInstance().appendLog("┣  ○  获取房间 -> 失败：" + result)
                                    .printLog();
                        } else {
                            LogHelper.getInstance().appendLog("┣  ●  获取房间 -> 成功").printLog();
                        }
                        break;
                    case Room_onJoinResult:
                        result = (int) rxBusMsgObj.getMsgBody();
                        if (isAutoModule) {
                            if (result == ErrorCode.AVD_OK) {
                                wakeLineAsyncTask();
                                isJoinRoomComplete = true;
                            } else {
                                wakeLineAsyncTask(true);
                                errorCheck(result, "加入房间");
                            }
                        } else if(joinRoomListener != null) {
                            if (result != ErrorCode.AVD_OK) {
                                joinRoomListener.error("加入房间失败：" + result);
                            } else {
                                joinRoomListener.success();
                            }
                        }

                        if (result != ErrorCode.AVD_OK) {
                            LogHelper.getInstance().appendLog("┣  ○  加入房间 -> 失败：" + result)
                                    .printLog();
                        } else {
                            LogHelper.getInstance().appendLog("┣  ●  加入房间 -> 成功").printLog();
                        }
                        break;
//                    case Meeting_setupMeeting:
//                        break;
                    case Meeting_initComplete:
                        wakeLineAsyncTask();
                        if (setupListener != null) {
                            setupListener.success();
                            RxBus.getInstance().post(new RxBusMsgObj(RxBusMsgObj.MsgTag.AVDManager_initCallback));
                        }
                        break;
                    case AVDEngine_onScheduleRoomResult:
                        ScheduleRoomBean roomBean = (ScheduleRoomBean) rxBusMsgObj.getMsgBody();
                        if (roomBean.getResult() != ErrorCode.AVD_OK && roomBean.getResult() != 40005) {
                            wakeLineAsyncTask(true);
                            isInitFailure = true;
                            isWorking = false;
                            errorCheck(roomBean.getResult(), "创建房间");
                        }
                        EngineConfigure.getInstance().createRoomCallback(roomBean);
                        break;
                    case Permission_Write_External_Storage:
                        EngineConfigure.getInstance().logFileConfig();
                        break;
                }

//                LogHelper.permissionHelper().printLog();
            }
        });
    }

    /**
     * 动态权限获取
     * @param context 上下文
     * @param listener 回调
     * @return
     */
    public AVDManager requestPermissions(Context context, RequestPermissionsListener listener) {
        this.context = context;
        this.permissionListener = listener;
        if (context instanceof Activity) {
            init();
            RequestPermissions.permissionHelper((Activity) context).requestAll();
        } else {
            if (listener != null) {
                listener.error("context is not activity");
            }
        }
        return this;
    }

    /**
     * 初始化AVD引擎
     * @param context 上下文
     * @param listener 回调
     * @return
     */
    public AVDManager initAVDEngine(Context context, InitAVDEngineListener listener) {
        this.initAVDEngineListener = listener;
        init();
        if (context == null) {
            if (listener != null) {
                listener.error("请使用AVDManager.permissionHelper().request(...)传入context！");
            }
            return this;
        }
        EngineConfigure.getInstance(context.getApplicationContext()).init(context);
        return this;
    }

    /**
     * 加入房间
     * @param roomParams 房间参数
     * @param listener 加入房间回调
     * @return
     */
    public AVDManager joinRoom(RoomManager.RoomParams roomParams, JoinRoomListener listener) {
        this.joinRoomListener = listener;
        this.roomParams = roomParams;
        if (roomParams == null) {
            if (listener != null) {
                listener.error("传入的RoomParams为空！");
            }
            return this;
        }
        String result = RoomManager.getInstance(roomParams).init();
        if (!IBaseService.SUCCESS.equals(result)) {
            if (listener != null) {
                listener.error(result);
            }
        }
        return this;
    }

    /**
     * 设置AVDSDK引擎监听
     * @param listener
     * @return
     */
    public AVDManager setAvdEngineListener(AVDEngine.Listener listener) {
        CallbackManager.getInstance().setAvdEngineListener_user(listener);
        return this;
    }

    /**
     * 设置AVDSDK加入房间事件监听
     * @param listener
     * @return
     */
    public AVDManager setRoomJoinListener(Room.JoinResultListener listener) {
        CallbackManager.getInstance().setRoomJoinListener_user(listener);
        return this;
    }

    /**
     * 设置AVDSDK房间事件监听
     * @param listener
     * @return
     */
    public AVDManager setRoomListener(Room.Listener listener) {
        CallbackManager.getInstance().setRoomListener_user(listener);
        return this;
    }

    /**
     * 设置AVDSDK视频事件监听
     * @param listener
     * @return
     */
    public AVDManager setMVideoListener(MVideo.Listener listener) {
        CallbackManager.getInstance().setMVideoListener_user(listener);
        return this;
    }

    /**
     * 设置AVDSDK屏幕共享事件监听
     * @param listener
     * @return
     */
    public AVDManager setMScreenListener(MScreen.Listener listener) {
        CallbackManager.getInstance().setMScreenListener_user(listener);
        return this;
    }

    /**
     * 设置AVDSDK用户事件监听
     * @param listener
     * @return
     */
    public AVDManager setMUserManagerListener(MUserManager.Listener listener) {
        CallbackManager.getInstance().setMUserManagerListener_user(listener);
        return this;
    }

    /**
     * 设置AVDSDK音频事件监听
     * @param listener
     * @return
     */
    public AVDManager setMAudioListener(MAudio.Listener listener) {
        CallbackManager.getInstance().setMAudioListener_user(listener);
        return this;
    }

    /**
     * 离开房间并清理现场
     */
    public void releaseRoom() {
        RequestPermissions.getInstance().dispose();
        LineAsyncTask.getInstance().dispose();
        RoomManager.getInstance().dispose();
        MeetingManager.getInstance().dispose();
        CallbackManager.getInstance().reset();
    }

    /**
     * 释放资源
     */
    @Override
    public void dispose() {
        if (disposable != null) {
            disposable.dispose();
            disposable = null;
        }

        RequestPermissions.getInstance().dispose();
        LineAsyncTask.getInstance().dispose();
        CallbackManager.getInstance().dispose();

        synchronized (LineAsyncTask.class) {
            if (serviceList.size() == 0) {
                RoomManager.getInstance().dispose();
                MeetingManager.getInstance().dispose();
                EngineConfigure.getInstance().dispose();
            } else {
                for (int i=0; i<serviceList.size(); i++) {
                    serviceList.get(serviceList.size() - 1 - i).dispose();
                }
            }
            serviceList.clear();
        }

        setupListener = null;
        context = null;
        isAutoModule = false;
        isAVDInit = false;
        isWorking = false;
        isInitFailure = false;
        isJoinRoomComplete = false;
        LogHelper.getInstance().appendLog("cn.tee3.manager.service :: AVDManager.dispose()")
                .printLog()
                .logBufferClear();
    }

    public interface RequestPermissionsListener {

        void success();

        void error(String errorCode);
    }

    public interface InitAVDEngineListener {

        void success();

        void error(String errorCode);
    }

    public interface JoinRoomListener {

        void success();

        void error(String errorCode);
    }

    public interface AVDSetupListener {

        void success();

        void error(String errorCode);
    }

}
