package com.baidu.rtc.sample;

import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatDelegate;

import com.baidu.rtc.BaiduRtcRoom;
import com.baidu.rtc.IRtcEventHandler;
import com.baidu.rtc.RtcParameterSettings;
import com.baidu.rtc.model.Constants;
import com.baidu.rtc.sample.data.RtcClientData;
import com.baidu.rtc.sample.util.JavaTypesHelper;
import com.baidu.rtc.sample.util.Utils;
import com.webrtc.Logging;

import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.ArrayList;

public class RtcRoomController extends IRtcEventHandler {
    private static final String TAG = "RtcRoomController";

    private BaiduRtcRoom mVideoRoom;
    private RtcClientData mClientData;
    private Activity mActivity;
    private boolean hasDemoteAudio;

    private IRtcEventHandler mCallback;

    public void onCreate(Activity activity, Intent intent, IRtcEventHandler callback) {
        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
        mActivity = activity;
        mCallback = callback;
        if (intent.getExtras() != null) {
            mClientData = intent.getExtras().getParcelable("data");
        }
        if (mClientData == null) {
            Log.e(TAG, "error InitRTCRoom mClientData is null !!");
            return;
        }
        mClientData.checkData(activity);
    }

    public BaiduRtcRoom initBdRtcRoom() {
        Logging.w(TAG, "mClientData:" + mClientData.dumpString());

        Log.i(TAG, "BaiduRTC(BRTC) SDK version is: " + BaiduRtcRoom.version());

        // 初始化
        mVideoRoom = BaiduRtcRoom.initWithAppID(mActivity, mClientData.mAppId, mClientData.mTokenStr);
        // 设置是否开启控制台log输出
        BaiduRtcRoom.setVerbose(true);
        // 状态上报
        mVideoRoom.enableStatsToServer(true, "online");
        // 设置回调
        mVideoRoom.setBaiduRtcEventHandler(this);
        return mVideoRoom;
    }

    public static boolean isHarmonyOs(){
        try {
            Class<?> buildExClass = Class.forName("com.huawei.system.BuildEx");
            Object osBrand = buildExClass.getMethod("getOsBrand").invoke(buildExClass);
            return "harmony".equalsIgnoreCase(osBrand.toString());
        }catch (Throwable e){
            return false;
        }
    }

    public void loginBdRtcRoom() {
        Log.i(TAG, "loginBdRtcRoom");
        RtcParameterSettings cfg = RtcParameterSettings.getDefaultSettings();
        if (mClientData.mIsWatch) {
            mClientData.videoWidth = 240;
            mClientData.videoHeight = 280;

            cfg.VideoCodec = RtcParameterSettings.VideoCodecId.JPEG;
            cfg.AudioCodec = RtcParameterSettings.AudioCodecId.PCMU;
            cfg.signalChannelMode = RtcParameterSettings.RtcSignalChannelMode.RTC_SIGNAL_CHANNEL_MODE_QUIC;
            cfg.EnableFixedResolution = true;
            cfg.forceSoftwareEncoder = true;
            cfg.forceSoftwareDecoder = true;
            cfg.VideoFps = 6;
            cfg.videoGopSize = 2 * cfg.VideoFps;
            if (isHarmonyOs()) {
                cfg.PreviewWidth = 360;
                cfg.PreviewHeight = 640;
            } else {
                cfg.PreviewWidth = 288;
                cfg.PreviewHeight = 352;
            }
            cfg.VideoWidth = mClientData.videoWidth;
            cfg.VideoHeight = mClientData.videoHeight;
            cfg.VideoMinkbps = 300;
            cfg.VideoMaxkbps = 500;
            cfg.disableDropFrame = true;
            cfg.EnableAudioLevel = false;
            cfg.enablePruneSignal = false;
            cfg.MaxNeteqDelay = 400;

            /** 关闭手表侧监控 */
//            mVideoRoom.enableStatsToServer(false, "online");
            Logging.w(TAG, "DoLogin, use Watch custom config! [" + cfg.VideoWidth + "x" + cfg.VideoHeight + "]" +
                    ",videoCodec:" + cfg.VideoCodec + ",audioCodec:" + cfg.AudioCodec);
        } else {
            mClientData.updateParamsSettings(cfg);

            /** H263 强制使用 176x144 */
            if (mClientData.mVideoCodec.equalsIgnoreCase(RtcParameterSettings.VideoCodecId.H263)) {
                cfg.VideoWidth = 176;
                cfg.VideoHeight = 144;
            }
        }


        // 设置参数
        mVideoRoom.setParamSettings(cfg, RtcParameterSettings.RtcParamSettingType.RTC_PARAM_SETTINGS_ALL);
        // 登录
        mVideoRoom.loginRtcRoomWithRoomName(mClientData.mRoomName,
                JavaTypesHelper.toLong(mClientData.mUserId, 1), mClientData.mUserName, new Constants.LoginOptions());
    }

    public RtcClientData getClientData() {
        return mClientData;
    }
    public void onResume() {
        hideBottomUIMenu();
        // 开始本地摄像头预览
        mVideoRoom.startPreview();
    }

    @Override
    public void onLoginSuccess(long roomId, long uid, int elapsed) {
        Logging.w(TAG, "login success, elapsed:" + elapsed + ",roomId:" + roomId);
    }

    @Override
    public void onConnectionStateChanged(int state, int reason) {
        Log.i(TAG, "onConnectionStateChanged, state:" + Utils.getStateString(state) + ",reason:" + reason);
        if (state == Constants.CONNECTION_STATE_DISCONNECTED) {
            Log.i(TAG, "Reconnecting.. CONNECTION_STATE_DISCONNECTED:" + reason);
            if (mClientData.mAutoReconnect) {
                hasDemoteAudio = false;
                return;
            }
            finishActivity();
        } else if (state == Constants.CONNECTION_STATE_RECONNECTING) {
            Log.i(TAG, "Reconnecting.. reason:" + reason);
        }
    }

    @Override
    public void onError(int error, String msg, Bundle bundle) {
        Log.i(TAG, "onError, error:" + error + ", " + Utils.getStateString(error) + ",bundle:" + bundle);
        if (error == Constants.ERR_RECONNECT_OVER_MAX_COUNT) {
            Log.e(TAG, "Over max reconnection count, finish Activity");
            toastMsg("超过最大重连次数 ");
        } else if (error == Constants.ERR_CHANNEL_IO_EXCEPTION) {
            Log.e(TAG, "channel io exception!");
            toastMsg("登录错误：" + msg);
            Log.e(TAG, "登录错误: " + msg);
            Logging.w(TAG, "onLoginRoomFail msg:" + msg + ",bundle:" + bundle);
        } else if (error == Constants.ERR_INTERNAL) {
            Log.e(TAG, "internal error, bundle:" + bundle);
        }
        finishActivity();
        Log.e(TAG, "onError, code:" + error + ",msg:" + msg + ",bundle:" + bundle);
    }

    @Override
    public void onUserKickOff(long uid) {
        Log.w(TAG, "onUserKickOff kick off: " + uid);
        if (uid == JavaTypesHelper.toLong(mClientData.mUserId, 1)) {
            toastMsg("被剔出房间");
            finishActivity();
        }
    }
    @Override
    public void onRoomDisbanded(long roomId) {
        Log.w(TAG, " onDisbandRoom : " + roomId);
        toastMsg("房间解散");
        finishActivity();
    }

    @Override
    public void onUserMessage(long uid, String message) {
        // 收到消息
        Log.d(TAG, " onUserMessage id: " + uid + " msg: " + message);
    }

    @Override
    public void onNetworkChanged(boolean isAvailable) {
        if (!isAvailable) {
            // show loading
            if (mClientData.mAutoReconnect) {
                toastMsg("当前无网络连接，恢复网络后自动重连");
            } else {
                toastMsg("当前无网络连接");
            }
        } else {
            toastMsg("网络连接可用");
        }
    }

    @Override
    public void onPullDemoteState(long uid, int network, int demote) {
        // 视频降级
        if (demote == Constants.NetWorkDownState.DEMOTE_AUDIO) {
            hasDemoteAudio = true;
        } else if (demote == Constants.NetWorkDownState.DEMOTE_SRC_VIDEO) {
            hasDemoteAudio = false;
        } else if (demote == Constants.NetWorkDownState.DEMOTE_NONE) {
            hasDemoteAudio = false;
        }
        String msg = "当前下行网络状态： " + uid;
        if (hasDemoteAudio) {
            msg += ", 已降级音频";
        }
        Logging.d(TAG, "onPullDemoteState, " + msg);
    }

    @Override
    public void onRemoteUserJoinRoom(long uid, String name) {
        Logging.d(TAG, "onRemoteUserJoinRoom uid:" + uid + ",name:" + name);
        if (mCallback != null) {
            mCallback.onRemoteUserJoinRoom(uid, name);
        }
    }

    @Override
    public void onRemoteUserLeaveRoom(long uid, String name) {
        Logging.d(TAG, "onRemoteUserLeaveRoom uid:" + uid + ",name:" + name);
        if (mCallback != null) {
            mCallback.onRemoteUserLeaveRoom(uid, name);
        }
    }

    @Override
    public void onStreamChangedState(long uid, String name, int opt, ArrayList<Constants.RtcStream> list) {
        Logging.d(TAG, "onStreamChangedState uid:" + uid + ",name:" + name + ", opt:" + opt);
        if (mCallback != null) {
            mCallback.onStreamChangedState(uid, name, opt, list);
        }
    }

    @Override
    public void onFirstVideoFrame(long uid, int width, int height) {
        Logging.d(TAG, "onFirstVideoFrame, uid:" + uid + ", width:" + width + ",height:" + height);
    }

    @Override
    public void onRemoteUserVideoAvailable(long uid, String name, boolean available) {
        Logging.d(TAG, "onRemoteUserVideoAvailable, uid:" + uid + ", available:" + available);
    }

    @Override
    public void onRemoteUserAudioAvailable(long uid, String name, boolean available) {
        Logging.d(TAG, "onRemoteUserAudioAvailable, uid:" + uid + ", available:" + available);
    }

    @Override
    public void onNetworkQuality(long userId, int txQuality, int rxQuality) {
        Logging.d(TAG, "onNetworkQuality userId:" + userId + " txQuality:" + txQuality + " rxQuality:" + rxQuality);
    }

    @Override
    public void onRoomDataMessage(ByteBuffer data) {
        Log.i(TAG, "onRoomDataMessage : " + Charset.defaultCharset().decode(data).toString());
    }

    private void checkIfFinishActivity() {
        if (mClientData.mAutoReconnect) {
            return;
        }
        finishActivity();
    }

    private void finishActivity() {
        mActivity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mVideoRoom.logoutRtcRoom();
                finish();
            }
        });
    }

    private void destroyAll() {
        mVideoRoom.registerAudioFrameObserver(null);
        mVideoRoom.destroy();
        Log.i(TAG, "destroyAll done");
    }

    public void finish() {
        destroyAll();
        mActivity.finish();
    }

    public void onDestroy() {
        destroyAll();
        Log.i(TAG, "onDestroy done");
    }


    private void toastMsg(String msg) {
        mActivity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(mActivity, msg, Toast.LENGTH_SHORT).show();
            }
        });
    }

    protected void hideBottomUIMenu() {
        // full screen no bottomUI.
        if (Build.VERSION.SDK_INT > 11 && Build.VERSION.SDK_INT < 19) { // lower api
            View v = mActivity.getWindow().getDecorView();
            v.setSystemUiVisibility(View.GONE);
        } else if (Build.VERSION.SDK_INT >= 19) {
            // for new api versions.
            View decorView = mActivity.getWindow().getDecorView();
            int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_FULLSCREEN;
            decorView.setSystemUiVisibility(uiOptions);
        }
    }
}
