package com.yidianling.im.helper;

import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Looper;
import android.text.TextUtils;

import com.netease.lava.nertc.sdk.NERtcConstants;
import com.netease.lava.nertc.sdk.NERtcEx;
import com.netease.lava.nertc.sdk.NERtcOption;
import com.netease.lava.nertc.sdk.NERtcParameters;
import com.netease.lava.nertc.sdk.video.NERtcEncodeConfig;
import com.netease.lava.nertc.sdk.video.NERtcVideoConfig;
import com.netease.nimlib.sdk.RequestCallback;
import com.netease.yunxin.nertc.nertcvideocall.bean.InvitedInfo;
import com.netease.yunxin.nertc.nertcvideocall.model.NERtcCallExtension;
import com.netease.yunxin.nertc.ui.CallKitNotificationConfig;
import com.netease.yunxin.nertc.ui.CallKitUI;
import com.netease.yunxin.nertc.ui.CallKitUIOptions;
import com.netease.yunxin.nertc.ui.service.DefaultIncomingCallEx;
import com.ydl.ydlcommon.modular.ModularServiceManagerKt;
import com.ydl.ydlcommon.utils.log.XLog;
import com.yidianling.im.R;
import com.yidianling.im.config.NimApplication;
import com.yidianling.im.config.NimSDKOptionConfig;
import com.yidianling.im.http.ImHttpImpl;
import com.yidianling.user.api.bean.UserResponseBean;
import com.yidianling.user.api.service.IUserService;

import org.jetbrains.annotations.NotNull;

import java.util.HashMap;
import java.util.Map;

import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;


public class NimUICallInit {

    private static boolean hasReportSupportLine = false;
    private static String curChannelName;

    public static void initNim2(Context context) {
        UserResponseBean.UserInfo userInfo = ModularServiceManagerKt.findRouteService(IUserService.class).getUserInfo();
        if (userInfo == null) return;
        String userId = userInfo.getUid();
        //防止网络波动的情况下多次触发LOGINED状态，导致呼叫组件重新初始化
        if (TextUtils.equals(userId, CallKitUI.INSTANCE.getCurrentUserAccId())) return;
        android.util.Log.e("qwert", userId + (Looper.myLooper() == Looper.getMainLooper()));
        String appKey = NimApplication.getInstance().getAppKey();
        NERtcParameters neRtcParameters = new NERtcParameters();
        neRtcParameters.set(NERtcParameters.KEY_SERVER_RECORD_AUDIO, true);
        neRtcParameters.set(NERtcParameters.KEY_SERVER_RECORD_VIDEO, true);
        NERtcEx.getInstance().setParameters(neRtcParameters);
        CallKitUIOptions options = new CallKitUIOptions.Builder()
                // 必要：音视频通话 sdk appKey，用于通话中使用
                .rtcAppKey(appKey)
                .logRootPath(NimSDKOptionConfig.getAppCacheDir(context) + "/yidianling")
                // 必要：当前用户 AccId
                .currentUserAccId(userId)
                .currentUserRtcUId(Long.parseLong(userId))
                // 通话接听成功的超时时间单位 毫秒，默认30s
                .timeOutMillisecond(30 * 1000L)
                .rtcCallExtension(new NERtcCallExtension(){
                    @Override
                    protected int joinChannel(String token, String channelName, long rtcUid) {
                        NERtcVideoConfig videoConfig = new NERtcVideoConfig();
                        videoConfig.frameRate = NERtcEncodeConfig.NERtcVideoFrameRate.FRAME_RATE_FPS_15;
                        videoConfig.width = 640;
                        videoConfig.height = 480;
                        videoConfig.degradationPrefer = NERtcVideoConfig.NERtcDegradationPreference.DEGRADATION_MAINTAIN_FRAMERATE;
                        NERtcEx.getInstance().setLocalVideoConfig(videoConfig);
                        // 音频设置 standard + speech
                        NERtcEx.getInstance().setAudioProfile(NERtcConstants.AudioProfile.STANDARD, NERtcConstants.AudioScenario.SPEECH);
                        // 设置 channel profile
                        NERtcEx.getInstance().setChannelProfile(NERtcConstants.RTCChannelProfile.COMMUNICATION);
                        return NERtcEx.getInstance().joinChannel(token, channelName, rtcUid);
                    }
                })
                // 此处为 收到来电时展示的 notification 相关配置，如图标，提示语等。
                .notificationConfigFetcher(invitedInfo -> new CallKitNotificationConfig(R.drawable.avchat_imcoming_call))
                // 收到被叫时若 app 在后台，在恢复到前台时是否自动唤起被叫页面，默认为 true
                .resumeBGInvitation(true)
                .incomingCallEx(new DefaultIncomingCallEx() {
                    @Override
                    public boolean onIncomingCall(@NotNull InvitedInfo invitedInfo) {
                        XLog.INSTANCE.i("incomingCallEx", invitedInfo.toString());
                        curChannelName = invitedInfo.channelName;
                        return super.onIncomingCall(invitedInfo);
                    }
                })
                .enableOrder(false)
//                .p2pAudioActivity(TestActivity.class)
//                .p2pVideoActivity(TestActivity.class)
                // 请求 rtc token 服务，若非安全模式则不需设置
                .rtcTokenService((uid, channel, callback) -> requestRtcToken(uid, channel, callback)) // 自己实现的 token 请求方法
                // 设置初始化 rtc sdk 相关配置，按照所需进行配置
                .rtcSdkOption(new NERtcOption())
                .enableMsgFilter(false)
                .enableCustomParser(false)
                .audio2VideoConfirm(true)
                // 呼叫组件初始化 rtc 范围，true-全局初始化，false-每次通话进行初始化以及销毁
                // 全局初始化有助于更快进入首帧页面，当结合其他组件使用时存在rtc初始化冲突可设置false
                .rtcInitScope(true)
                .build();
// 若重复初始化会销毁之前的初始化实例，重新初始化
        CallKitUI.init(context.getApplicationContext(), options);
    }

    @SuppressLint("CheckResult")
    private static void requestRtcToken(long uid, String channel, RequestCallback<String> callback) {
        Map<String, String> body = new HashMap<>();
        if (channel != null) {
            body.put("channelName", channel);
        }
        body.put("uid", String.valueOf(uid));
        ImHttpImpl.Companion.getInstance().getImApi().nim2Token(body)
                .subscribeOn(Schedulers.io())
                .observeOn(Schedulers.io())
                .subscribe(resp -> {
                    curChannelName = null;
                    if (resp.code == 200) {
                        callback.onSuccess(resp.data);
                    } else {
                        XLog.INSTANCE.i("requestRtcToken", resp.msg);
                        callback.onFailed(resp.code);
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                        curChannelName = null;
                        callback.onException(throwable);
                    }
                });
    }

    @SuppressLint("CheckResult")
    public static void reportSupportLine() {
        if (hasReportSupportLine) return;
        Map<String, Object> report = new HashMap<>();
        report.put("callKeys", new String[]{"netease_app2"});//支持云信2.0呼叫通话
        ImHttpImpl.Companion.getInstance().getImApi()
                .reportSupportLine(report)
                .subscribeOn(Schedulers.io())
                .subscribe(resp -> {
                    if (TextUtils.equals(resp.code, "200")) {
                        hasReportSupportLine = true;
                    }
                });
    }
}
