package com.hh.lib_ampe.utils;

import static com.hh.lib_base.Constants.LogcatValue.NET_ERROR;
import static com.hh.lib_base.Constants.LogcatValue.WARP;

import android.content.Context;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.DisplayMetrics;

import com.alipay.arome.aromecli.AromeInit;
import com.alipay.arome.aromecli.AromeInitOptions;
import com.alipay.arome.aromecli.AromeServiceInvoker;
import com.alipay.arome.aromecli.AromeServiceTask;
import com.alipay.arome.aromecli.requst.AromeActivateRequest;
import com.alipay.arome.aromecli.requst.AromeLaunchAppRequest;
import com.alipay.arome.aromecli.requst.AromeSendEventRequest;
import com.alipay.arome.aromecli.response.AromeResponse;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.hh.lib_ampe.bean.BaseAmpeAppletResultBean;
import com.hh.lib_ampe.bean.BaseAmpeRequestBean;
import com.hh.lib_ampe.listenr.AmpeResultListener;
import com.hh.lib_ampe.listenr.MiniProgramResultListener;
import com.hh.lib_base.BaseApplication;
import com.hh.lib_base.ConfigData;
import com.hh.lib_base.Constants;
import com.hh.lib_base.bean.device.DeviceConfigResultBean;
import com.hh.lib_base.log.AppLogUtils;
import com.hh.lib_base.log.UploadLogUtils;
import com.hh.lib_base.utils.GsonUtils;
import com.hh.lib_base.utils.ShortenLogUtils;
import com.hh.lib_base.utils.StringUtils;
import com.hh.lib_base.utils.device.DeviceUtils;

import org.json.JSONObject;

import java.util.ArrayList;

/**
 * @author xwh
 * time 2024/8/22
 * Description: AMPE
 **/
public class AromeInvoker {

    private volatile static AromeInvoker aromeInvoker;
    private volatile AmpeResultListener ampeResultListener;
    private volatile MiniProgramResultListener miniProgramResultListener;
    private String appletId;

    private  int appletOperationTimeout= 30;
    private String packageName="";


    /**
     * @author xwh
     * Time 2024/8/23
     * Description: AppLication 初始化
     **/
    public static void init(Context context) {
        // AMPE
        AromeInit.attachApplicationContext(context);
    }

    public static AromeInvoker getInstance(AmpeResultListener listener) {
        if (aromeInvoker == null) {
            synchronized (AromeInvoker.class) {
                if (aromeInvoker == null) {
                    aromeInvoker = new AromeInvoker();
                    aromeInvoker.setAmpeResultListener(listener);
                    aromeInvoker.registerBridgeExtension();
                }
            }
        }
        aromeInvoker.setAmpeResultListener(listener);
        return aromeInvoker;
    }

    public static AromeInvoker getAromeInvoker() {
        return aromeInvoker;
    }

    /**
     * @author xwh
     * Time 2024/8/23
     * Description: 注册小程序通道，保持唯一，架包中是注册一个new一个
     **/
    private void registerBridgeExtension() {
        if (ampeResultListener != null) {
            ampeResultListener.ampeChannelSuccrss();
        }
        AppLogUtils.e("registerBridgeExtension");
        String logLine = (new Throwable().getStackTrace())[0].toString();
        UploadLogUtils.sendLogs("通道建立开始监听---", "", logLine, "AMPE通道建立成功！");
        // 监听小程序发出来的获取硬件配置通知,通道建立
        AromeServiceInvoker.registerBridgeExtension(new AromeServiceInvoker.BridgeExtension() {
            @Override
            public void onCalled(String action, String params, AromeServiceInvoker.BridgeCallback bridgeCallback) {
                BaseAmpeRequestBean ampeAppletRequestBean = GsonUtils.getGson().fromJson(params, BaseAmpeRequestBean.class);
                if(ampeAppletRequestBean==null){
                    return;
                }
                ampeAppletRequestBean.setSourceParams(params);
                String logLine = (new Throwable().getStackTrace())[0].toString();
                StringBuilder logContentSb = new StringBuilder();
                logContentSb.append("onCalled").append(WARP)
                        .append("action = ").append(action).append(WARP)
                        .append("params = ").append(ampeAppletRequestBean.toString());
                UploadLogUtils.sendLogs("小程序通道建立---入参---", "", logLine, logContentSb.toString());
                String actionName = ampeAppletRequestBean.getAction();
                if (StringUtils.isNull(actionName)) {
                    return;
                }
                if(ampeResultListener!=null){
                    ampeResultListener.onCalled(action,ampeAppletRequestBean,bridgeCallback);
                }
            }
        });

    }


    /**
     *
     * @author xwh
     * Time 2024/8/23
     * Description: 配置小程序
     *
    **/
    public void initAndActive(final DeviceConfigResultBean ampeConfigResultBean,
                               String packageName,
                               int appletOperationTimeout) {
        this.appletOperationTimeout = appletOperationTimeout;
        this.packageName = packageName;
        if (TextUtils.isEmpty(packageName) && BaseApplication.getContext() != null) {
            packageName = BaseApplication.getContext().getPackageName();
        }
        if (miniProgramResultListener != null) {
            miniProgramResultListener.onStartApplet();
        }

        // 主题参数配置
        Bundle themeConfig = new Bundle();
        // 不需要登录
        themeConfig.putBoolean("needLogin", false);
        //是否隐藏状态栏 默认false——根据下拉通知栏配置
//        themeConfig.putBoolean("hideStatusBar", false);
        themeConfig.putBoolean("hideStatusBar", ampeConfigResultBean.isForbidPullDown());
        //是否隐藏导航栏 默认false
        themeConfig.putBoolean("hideNavigationBar", false);
        //是否隐藏标题栏胶囊按钮 默认false不隐藏，true隐藏。配置右上角三个圆点和X
        AppLogUtils.e("三个圆点hideNavigationBar:" + ampeConfigResultBean.isHideNavigationBar());
        themeConfig.putBoolean("hideOptionMenu", ampeConfigResultBean.isHideNavigationBar());
//        themeConfig.putBoolean("hideOptionMenu", true);
        //超时时间 单位秒，默认30秒 建议传大于10的值
//        themeConfig.putInt("timeOut", 30);
        AppLogUtils.e("appletOperationTimeout:" + appletOperationTimeout);
        if (appletOperationTimeout > 0) {
            themeConfig.putInt("operationTimeoutPeriod", appletOperationTimeout);
        } else {
            themeConfig.putInt("operationTimeoutPeriod", 30);
        }


//        // 初始化多窗口设置
//        final int[] rect = new int[]{0, 0, 1000, 1600};
//        //是否使用freeform打开小程序 默认false
        themeConfig.putBoolean("enableFloatWindow", false);
//        //freeform窗口大小 需配合enableFloatWindow 值为true使用
//        themeConfig.putIntArray("windowBounds", rect);


//         配置黑名单 黑名单中的小程序可全屏显示
//        如果enableFloatWindow值为true，需要全屏显示的小程序配置到黑名单中可全屏显示
//        ArrayList<String> blackList = new ArrayList<>();
//        blackList.add("2021002163620647");
//        themeConfig.putStringArrayList("floatWindowBlacklist", blackList);

        // 获取设备宽高
        DisplayMetrics dm = BaseApplication.getContext().getResources().getDisplayMetrics();
        int displayWidth = dm.widthPixels;
        int displayHeight = dm.heightPixels;
        AppLogUtils.e("displayWidth--" + displayWidth);
        AppLogUtils.e("displayHeight--" + displayHeight);
        //竖屏配置，若没有可以不配置
        Bundle portrait = new Bundle();
        //竖屏默认默认值是2 可参考https://opendocs.alipay.com/mini/00v8et?pathHash=8d2d3fa2#3.1%20%E5%90%AF%E5%8A%A8
        portrait.putInt("showType", 2);
        //横屏配置，若没有可以不配置
        Bundle landscape = new Bundle();
        //横屏默认值是123
        landscape.putInt("showType", 2);
//        AppLogUtils.e("showType--" + portrait.getInt("showType"));
        String deviceModel = DeviceUtils.getDeviceModel();
        if (deviceModel.contains(Constants.DeviceModel.ZP_A50)) {
            // 紫鹏X5的配置。按照获取的值左右有边距
            //竖屏配置的宽度  默认750 小程序显示的宽度750就是按给定窗口的大小显示，如果是375则是给定窗口大小的一半显示
            portrait.putInt("launchWidth", 750);
            // 横屏配置的宽度
            landscape.putInt("launchWidth", 750);
        } else {
            //竖屏配置的宽度  默认750 小程序显示的宽度750就是按给定窗口的大小显示，如果是375则是给定窗口大小的一半显示
            portrait.putInt("launchWidth", displayWidth);
            // 横屏配置的宽度
            landscape.putInt("launchWidth", displayWidth);
        }


        themeConfig.putBundle("portrait", portrait);
        themeConfig.putBundle("landscape", landscape);


        // 设备信息配置
        Bundle deviceConfig = new Bundle();
        // 防止小程序页面左右有白边
        deviceConfig.putString("needRealMetrics", "yes");
        //用于接收广播的应用包名
        deviceConfig.putString("packageName", packageName);
        deviceConfig.putBoolean("needLogin", false);


        int loginMode = 0;
        if (appletOperationTimeout > 0) {
            loginMode = 2;
        }
        AppLogUtils.e("loginMode:" + loginMode);

        final AromeInitOptions options = new AromeInitOptions.Builder()
                // 小程序页面上的悬浮框  0 手动登入登出 1 悬浮球头像露出，用户可登出 可选配置  2 提示超时退出通知
                .loginMode(loginMode)
                //硬件名称 可选配置
                //.hardwareName("")
                .deviceConfig(deviceConfig)//设备信息配置，一般来说，如果不需要接收广播不需要该配置
                //全局主题参数配置，AromeLaunchRequest中的themeConfig是局部配置，影响范围为这一次启动小程序
                //局部配置优先级高于全局配置
                .themeConfig(themeConfig)
                .build();

        AromeActivateRequest activateRequest = new AromeActivateRequest();
        activateRequest.deviceId = ampeConfigResultBean.getSn();
        activateRequest.hostAppId = ampeConfigResultBean.getAmpeAppid();
        activateRequest.productId = Long.parseLong(ampeConfigResultBean.getProductId());//你自己的productId
        activateRequest.signature = ampeConfigResultBean.getSignature();

        // 日志打印和保存（本地和网络）
        String logLine=    (new Throwable().getStackTrace())[0].toString();
        UploadLogUtils.sendLogs("小程序初始化","",logLine,
                "deviceId = " + ampeConfigResultBean.getSn() +
                "hostAppId = " + ampeConfigResultBean.getAmpeAppid() +
                "productId = " + ampeConfigResultBean.getProductId() +
                "signature = " + ampeConfigResultBean.getSignature());

        AromeInit.initAndActivate(options, activateRequest, new AromeInit.Callback() {
            @Override
            public void postInit(boolean success, int errorCode, String errorMsg) {
                // 非主线程中
                String logLine=    (new Throwable().getStackTrace())[0].toString();
                UploadLogUtils.sendLogs("小程序初始化结果","",logLine,
                        "postInit result"+
                        "success = " + success+
                        "errorCode = " + errorCode+
                        "errorMsg = " + errorMsg);

                if (errorCode == 0) {
                    // 成功
                    appletId = ampeConfigResultBean.getMiniProgramAppid();
                    AppLogUtils.e("initAndActive--appId&appletId:" + appletId);
                    // 启动小程序
                    launchApplet(appletId);
                } else if (errorCode == 2002) {
                    // 可能是设备ampe未授权
                    if(miniProgramResultListener!=null){
                        miniProgramResultListener.onInitAppletFailed(errorCode+"","设备ampe未授权");
                    }
                } else if (errorCode == 3 || errorCode == 2007) {
                    // 检查引擎
                    if(miniProgramResultListener!=null){
                        miniProgramResultListener.onInitAppletFailed(errorCode+"",
                                "设备ampe启动失败--" + errorCode + "--" + errorMsg + "   请重装引擎");
                    }
                } else {
                    if(miniProgramResultListener!=null){
                        miniProgramResultListener.onInitAppletFailed(errorCode+"",
                                "设备ampe启动失败--" + errorCode + "--" + errorMsg);
                    }
                }


            }

            @Override
            public void serverDied() {
                if(miniProgramResultListener!=null){
                    miniProgramResultListener.onInitAppletFailed("",
                            "设备ampe启动失败--serverDied");
                }
                String logLine=    (new Throwable().getStackTrace())[0].toString();
                UploadLogUtils.sendLogs(NET_ERROR,"小程序初始化结果","",logLine,
                        "设备ampe启动失败--serverDied",true);
            }
        });

    }

    /**
     *
     * @author xwh
     * Time 2024/8/23
     * Description: 启动小程序
     *
    **/
    public void launchApplet(String appId) {
        if (miniProgramResultListener != null) {
            miniProgramResultListener.onStartApplet();
        }
        String appletHomePage = "";
        DeviceConfigResultBean deviceConfigBean=ConfigData.getDeviceConfigResultBean();
        if (deviceConfigBean != null &&
                !TextUtils.isEmpty(deviceConfigBean.getAppletEnterPageUrl())) {
            appletHomePage = deviceConfigBean.getAppletEnterPageUrl();
        }
        String logLine = (new Throwable().getStackTrace())[0].toString();
        UploadLogUtils.sendLogs("启动小程序", "appId = " + appId+
                "  appletHomePage = " + appletHomePage, logLine, "开始启动小程序...");
        AromeLaunchAppRequest request = new AromeLaunchAppRequest();
        // 设备信息配置
        Bundle themeConfig = new Bundle();
        // 不需要登录
        themeConfig.putBoolean("needLogin", false);
        //支持指定displayId 如果不指定 直接在默认的屏幕显示
        //themeConfig.putInt("displayId", displayId);
        // 是否使用自定义的
        themeConfig.putBoolean("useCustomTitlebar", true);
        request.themeConfig = themeConfig;
        request.appId = appId;
        if (!TextUtils.isEmpty(appletHomePage)) {
            request.page = appletHomePage;
        }

        //如果需要黑白模式切换的逻辑 query需要传入 "openThemeSwitch=1"
        //不需要可以不传
//        request.query = "";
        // 江西就业之家
//        request.query = "ampe=tzsw";
        request.query = "is_ampe=true";
        //启动前是否关闭所有小程序，默认false，建议传true，减少性能开销
        request.closeAllApp = true;
        //注册硬件能力list
        // 只有注册硬件能力 AromeServiceInvoker.registerBridgeExtension才能收到回调
        request.extensionList = getExtensionList();
        //局部的配置只影响当前这一次启动，如果没有特殊需要可以不传
        //不传则采用初始化配置的全局配置
        // request.themeConfig = themeConfig;
        AromeServiceInvoker.invoke(request, new AromeServiceTask.Callback<AromeResponse>() {
            @Override
            public void onCallback(final AromeResponse aromeResponse) {
                // 此回调不在主线，如需要刷新UI 请自行切线程
                // {success=false, code=1001, message='token invalid!'}
                // {success=true, code=0, message='null'}
                AppLogUtils.e("launchApplet-- onCallback = " + aromeResponse.toString());

                int code = aromeResponse.code;


                if (code == 0 || code == 1000) {
                    if (miniProgramResultListener != null) {
                        miniProgramResultListener.onStartAppletSuccess();
                    }
                    // 防止多次点击，导致建立多个通道，信息也多次
//                    appletListen();
                } else {
                    if (miniProgramResultListener != null) {
                        miniProgramResultListener.onStartAppletFailed("" + code,
                                code == 1001 ? "设备ampe未授权" : "启动小程序失败--" + aromeResponse.toString());
                    }
                }
                String logLine = (new Throwable().getStackTrace())[0].toString();
                UploadLogUtils.sendLogs("启动小程序结果", "", logLine,
                        "code = " + code + "  aromeResponse = " + aromeResponse.toString());

            }
        });
    }

    
    /**
     *
     * @author xwh
     * Time 2024/9/5
     * Description: 各类监听，主动给小程序
     *
    **/
    public void sendMessageToApplet(String eventName, String eventData) {
        AppLogUtils.i("主动发消息给小程序eventName：" + eventName + "---发送内容eventData：" + eventData);


        AromeSendEventRequest request = new AromeSendEventRequest();
        request.eventName = eventName;

        JSONObject object = new JSONObject();
        try {
            // 勿动key，对外的文档key
            object.put("data", eventData);
        } catch (Throwable t) {

        }
        request.eventData = object.toString();

        AppLogUtils.e("主动发消息给小程序object：" + object.toString());


        AromeServiceInvoker.invoke(request, new AromeServiceTask.Callback<AromeResponse>() {
            @Override
            public void onCallback(AromeResponse response) {
                //自行处理事件发送成功后的回调
                AppLogUtils.e(eventName + "---" + response.toString());

                String type = "";

                if (eventName.equals(Constants.Ampe.EVENT_IDCard_LISTENER)) {
                    // 身份证持续监听
                    type = Constants.LogcatValue.LOG_NODE_IDCARD;
                } else if (eventName.equals(Constants.Ampe.EVENT_QR_LISTENER)) {
                    // 二维码持续监听
                    type = Constants.LogcatValue.LOG_NODE_QR;
                } else if (eventName.equals(Constants.Ampe.EVENT_MICROPHONE_LISTENER)) {
                    // 麦克风持续监听
                    type = Constants.LogcatValue.LOG_NODE_MICROPHONE;
                } else if (eventName.equals(Constants.Ampe.EVENT_INFRARED_INDUCTION_LISTENER)) {
                    // 开启红外感应持续监听
                    type = Constants.LogcatValue.LOG_NODE_INFRARED_INDUCTION;
                }else  if(eventName.equals(Constants.Ampe.EVENT_SOCIALSECURITYCARD_LISTENER)){
                    //社保卡监听
                    type=Constants.LogcatValue.LOG_SOCIAL_SECURITY_CARD;
                }else if (eventName.equals(Constants.Ampe.EVENT_NFC_CPUCARDLISTENER)){
                    //CPU卡监听
                    type=Constants.LogcatValue.LOG_NFC_CPU;
                }else if (eventName.equals(Constants.Ampe.ACTION_INITM1LISTENER)){
                    //M1卡监听
                    type=Constants.LogcatValue.LOG_M1CARD;
                }else if(eventName.equals(Constants.Ampe.ACTION_LISTENER_INIT_ASR)){
                    //ASR 语音识别
                    type=Constants.LogcatValue.LOG_ASR;
                }

                // 日志行数——对应web端"日志标签"
                String logLine = (new Throwable().getStackTrace())[0].toString();
                StringBuilder logContentSb = new StringBuilder();
                logContentSb.append(ShortenLogUtils.shortenLog(eventData));
                logContentSb.append(WARP).append("aromeResponse = ")
                        .append(response);
                UploadLogUtils.sendLogs(type,"---主动推送给小程序结果---"+eventName,logLine,logContentSb.toString());

                if (response.code == 1001) {
                    if(TextUtils.isEmpty(packageName)&&BaseApplication.getContext()!=null){
                        packageName=BaseApplication.getContext().getPackageName();
                    }
                    // 失效
                    initAndActive(ConfigData.getDeviceConfigResultBean(),packageName,appletOperationTimeout);
                }

            }
        });

    }

    /**
     *
     * @author xwh
     * Time 2024/9/26
     * Description: 硬件功能未启用
     *
    **/
    public void hardwareNotEnabled(BaseAmpeRequestBean dataBean, AromeServiceInvoker.BridgeCallback bridgeCallback){
        if(dataBean==null){
            return;
        }
        BaseAmpeAppletResultBean bean = new BaseAmpeAppletResultBean();
        bean.setAction(dataBean.getAction());
        bean.setEvent(dataBean.getEvent());
        bean.setTaskId(dataBean.getTaskId());
        bean.setSuccess(false);
        bean.setMessage("该功能未启用，请联系技术支持。");
        try {
            JsonObject jsonObject = GsonUtils.getGson().toJsonTree(bean).getAsJsonObject();
            if (bridgeCallback != null) {
                bridgeCallback.callback(jsonObject.toString());
            }
            String logLine = (new Throwable().getStackTrace())[0].toString();
            UploadLogUtils.sendLogs("模块-未启用",dataBean.getAction(),logLine,
                     "jsonObject = " + jsonObject);
        } catch (Throwable t) {
            AppLogUtils.e("onCalled--t" + t);
        }
    }
    public static void onRelease(){
        aromeInvoker = null;
    }

    // ampe通道名称
    private ArrayList<String> getExtensionList() {
        ArrayList<String> extensionList = new ArrayList<>();

        extensionList.add("HHCommunication");
        return extensionList;
    }


    public void setAmpeResultListener(AmpeResultListener ampeResultListener) {
        this.ampeResultListener = ampeResultListener;
    }


    public void setMiniProgramResultListener(MiniProgramResultListener miniProgramResultListener) {
        this.miniProgramResultListener = miniProgramResultListener;
    }
}
