package com.example.kingway.ptt;

import android.util.Log;

import timber.log.Timber;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**解析接收到的AT指令*/
public class CallBackResolution {
    private static String TAG = "PTT_RX";
    private static String indexGroupId = "";//用户所在群组Id
    private static String indexGroupName = "";//用户所在群组名称
    private static List<GroupMemberInfoDto> memberInfoDtos = new ArrayList<>();
    private static int speckType = 1;
    private static String talkId = "";
    private static String talkName = "";
	private static ArrayList<GroupInfoDto> groupInfos = new ArrayList<>();
    private static String oldLoginSate = "00";
    private static int logNum = 0;
    private static long offlineTime = 0;
    private static boolean loginState = false;
    private static String pttLoginStatus = "00"; // 00-未登录 01-登录中 02-已登录
    private static String pttLoginId = "";

    public static String getPttLoginStatus() {
        return pttLoginStatus;
    }

    public static String getPttLoginId() {
        return pttLoginId;
    }

    public static void resetPttLoginStatus() {
        pttLoginStatus = "00";
        pttLoginId = "";
    }

    public static String getCurrentGroupId() {
        return indexGroupId;
    }

    public static String getCurrentGroupName() {
        return indexGroupName;
    }

    public static void at_OEM_AT_cb(List<String> lisHex){
        if (lisHex.size() == 0) {
            return;
        }

        String ngx = "\\u";
        try {
            Timber.tag(TAG).i( "lisHex-->" + lisHex.toString());
            String firstHex = lisHex.get(0);
            String errorNum = lisHex.get(1);
            Timber.tag(TAG).d( "at_OEM_AT_cb firstHex: " + firstHex + ", errorNum: " + errorNum);
            switch (firstHex){
                case "82"://登录状态通知指令
                    String loginId = lisHex.get(2) + "" + lisHex.get(3) + "" + lisHex.get(4) + "" + lisHex.get(5);
                    pttLoginStatus = errorNum;
                    pttLoginId = loginId;
                    Timber.tag(TAG).d("PTT login status: "+pttLoginStatus+", id: "+pttLoginId);
                    // 实时推送状态到前端
                    CallBackUtil.callBackLoinState(errorNum, loginId);
                    loginState = isLoginConflict(errorNum);
                    CallBackUtil.callBackLoginConflict(loginState);
                    if (loginState) {
                        Timber.tag(TAG).w("Login conflict detected, showing conflict dialog");
                        com.stand.standapp.MainActivity.executeJs("updatePttLoginStatus('" + pttLoginStatus + "','" + pttLoginId + "')");
                        com.stand.standapp.MainActivity.showPttConflictDialog();
                    }
                    if ("00".equals(errorNum)) {
                        com.stand.standapp.MainActivity.executeJs("updatePttLoginStatus('" + pttLoginStatus + "','" + pttLoginId + "')");
                    }
                    if ("02".equals(errorNum)) {
                        com.stand.standapp.MainActivity.onPttLoginSuccess();
                        com.stand.standapp.MainActivity.executeJs("updatePttLoginStatus('" + pttLoginStatus + "','" + pttLoginId + "')");
                    }
                    break;

                case "a2"://账号有视频功能
                    CallBackUtil.callBackHaveVideo();
                    break;

                case "0d"://查询群组返回状态
                    if (errorNum.equals("00")){
                        CallBackUtil.callBackGroupInfo(groupInfos);
                    }
                    //CallBackUtil.callBackOnGroupSuccess(errorNum.equals("01")? false : true);
                    break;

                case "0e"://查询群组成员返回状态
                    CallBackUtil.callBackOnMemberSuccess(errorNum.equals("01")? false : true, memberInfoDtos);
                    break;

                case "0b"://发起讲话返回状态
                    Timber.tag(TAG).d( "at_OEM_AT_cb ptt speak...");
                    CallBackUtil.callBackSpeakPlaySuccess(errorNum.equals("00")? true : false);
                    break;

                case "0c"://结束讲话返回状态
                    Timber.tag(TAG).d( "at_OEM_AT_cb speak end...");
                    CallBackUtil.callBackSpeakReleaseSuccess(errorNum.equals("00")? true : false);
                    break;

                case "80"://返回群组信息
                    Timber.tag(TAG).d( "at_OEM_AT_cb get group info: " + lisHex);
                    StringBuilder strGroup = new StringBuilder();
                    String groupId = lisHex.get(6) + "" + lisHex.get(7) + "" + lisHex.get(8) + "" + lisHex.get(9);
                    int groupNo = Integer.valueOf((lisHex.get(4) + "" + lisHex.get(5)), 16);
                    int groupCount = Integer.valueOf((lisHex.get(10) + "" + lisHex.get(11)), 16);

                    try {
                        int numB = 13;
                        int size = lisHex.size() - 12;
                        size = (size / 2) - 1;
                        for (int i = 0; i < size; i++) {
                            if (i == 0) {
                                strGroup.append(ngx).append(lisHex.get(i + numB)).append(lisHex.get(i + numB - 1));
                            } else {
                                strGroup.append(ngx).append(lisHex.get(i + numB + 1)).append(lisHex.get(i + numB));
                                numB = numB + 1;
                            }
                        }
                    } catch (Exception e) {
                        Timber.tag(TAG).e(e, "Decode hex failed");
                    } finally {
                        String tempTxt = "";
                        tempTxt = unicodeToString(strGroup.toString());
                        Timber.tag(TAG).i( "  组名称  " + tempTxt);
                        CallBackUtil.callBackGroupInfo(groupId, tempTxt, groupNo, groupCount);
                        Timber.tag(TAG).d( "at_OEM_AT_cb group info groupId: " + groupId + ", groupNo: " + groupNo+", groupCount: " +groupCount);
                        if (1 == groupNo) groupInfos.clear();
                        GroupInfoDto groupInfo = new GroupInfoDto(groupId, tempTxt, groupNo, groupCount);
                        groupInfos.add(groupInfo);
                    }
                    break;

                case "81"://返回群成员信息
                    StringBuilder groupMemberName = new StringBuilder();
                    String status = lisHex.get(1);
                    boolean haveVideo = lisHex.get(10).equals("01") ? true : false;
                    String memberId = lisHex.get(6) + "" + lisHex.get(7) + "" + lisHex.get(8) + "" + lisHex.get(9);
                    int memberNo = Integer.valueOf((lisHex.get(4) + "" + lisHex.get(5)), 16);

                    try {
                        int numB = 12;
                        int size = lisHex.size() - 11;
                        size = (size / 2) - 1;
                        for (int i = 0; i < size; i++) {
                            if (i == 0) {
                                groupMemberName.append(ngx).append(lisHex.get(i + numB)).append(lisHex.get(i + numB - 1));
                            } else {
                                groupMemberName.append(ngx).append(lisHex.get(i + numB + 1)).append(lisHex.get(i + numB));
                                numB = numB + 1;
                            }
                        }
                    } catch (Exception e) {
                        Timber.tag(TAG).e(e, "Decode hex failed");
                    } finally {
                        String tempTxt = unicodeToString(groupMemberName.toString());
                        GroupMemberInfoDto infoDto = new GroupMemberInfoDto(memberId, tempTxt, status, memberNo, haveVideo);
                        if (memberNo == 1) memberInfoDtos.clear();
                        memberInfoDtos.add(infoDto);
                    }
                    break;

                case "83"://讲话用户信息通知
                    if (lisHex.get(1).equals("00")) {
                        speckType = 0;
                    } else {
                        speckType = 1;
                    }

                    talkId = lisHex.get(2) + "" + lisHex.get(3) + "" + lisHex.get(4) + "" + lisHex.get(5);
                    List<String> stringsSpker = new ArrayList<>();
                    try {
                        int numA = 6;
                        int numB = 7;
                        int size = lisHex.size() - 6;
                        size = (size / 2) - 1;
                        for (int i = 0; i < size; i++) {
                            if (i == 0) {
                                stringsSpker.add(ngx + lisHex.get(i + numB) + "" + lisHex.get(i + numA));
                            } else {
                                int start = i + numB;
                                int end = i + numB + 1;
                                stringsSpker.add(ngx + lisHex.get(end) + "" + lisHex.get(start));
                                numB = numB + 1;
                            }

                        }

                    } catch (Exception e) {
                        Timber.tag(TAG).e(e, "Decode hex failed");
                    } finally {
                        String tempTxt = "";
                        for (int i = 0; i < stringsSpker.size(); i++) {
                            tempTxt += unicode(stringsSpker.get(i));
                        }
                        talkName = tempTxt;
                        CallBackUtil.callBackNotifySpker(speckType, indexGroupId, indexGroupName, talkId, talkName);
                    }
                    break;

                case "8b"://通知音频播放的状态
                    int notifyPlayStatus = Integer.parseInt(lisHex.get(2));
                    if (notifyPlayStatus == 0){
                        talkId = "";
                        talkName = "";
                    }
                    CallBackUtil.callBackNotifyPlayStatus(notifyPlayStatus, speckType, indexGroupId, indexGroupName, talkId, talkName);
                    break;

                case "84"://提示信息通知
                    List<String> stringsTalk = new ArrayList<>();
                    try {
                        int numA = 2;
                        int numB = 3;
                        int size = lisHex.size() - 2;
                        size = (size / 2) - 1;
                        for (int i = 0; i < size; i++) {
                            if (i == 0) {
                                stringsTalk.add(ngx + lisHex.get(i + numB) + "" + lisHex.get(i + numA));
                            } else {
                                int start = i + numB;
                                int end = i + numB + 1;
                                stringsTalk.add(ngx + lisHex.get(end) + "" + lisHex.get(start));
                                numB = numB + 1;
                            }

                        }

                    } catch (Exception e) {
                        Timber.tag(TAG).e(e, "Decode hex failed");
                    } finally {
                        String tempTxt = "";
                        for (int i = 0; i < stringsTalk.size(); i++) {
                            tempTxt += unicode(stringsTalk.get(i));
                        }
                        int code=-1;
                        if(tempTxt.equals("退出临时呼叫")){
                            code=0;
                        } else if (tempTxt.startsWith("临时呼叫临时群组")) {
                            code=1;
                        } else if (tempTxt.equals("呼出失败")||tempTxt.equals("呼叫失败")) {
                            code=2;
                        } else if (tempTxt.equals("呼叫成功")||tempTxt.equals("呼出成功")) {
                            code=3;
                        }else{
                            code=-1;
                        }

                        Timber.tag(TAG).i( "  临时讲话 信息通知的指令  " + tempTxt + " code=" + code);
                        CallBackUtil.callBackTempCallNotify(tempTxt);

                        // 处理临时呼叫页面逻辑
                        if (code == 1) {
                            // 临时呼叫临时群组 → 打开临时呼叫页面
                            try {
                                android.content.Intent intent = new android.content.Intent(
                                    com.stand.standapp.MyApplication.getAppInstance(),
                                    com.stand.standapp.TempCallActivity.class
                                );
                                // 从84消息中提取临时群名称，格式为"临时呼叫XXX"
                                String tempGroupName = "临时会话";
                                if (tempTxt.startsWith("临时呼叫") && tempTxt.length() > "临时呼叫".length()) {
                                    tempGroupName = tempTxt.substring("临时呼叫".length());
                                }
                                intent.putExtra("group_name", tempGroupName);
                                intent.addFlags(
                                    android.content.Intent.FLAG_ACTIVITY_NEW_TASK |
                                    android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP
                                );
                                com.stand.standapp.MyApplication.getAppInstance().startActivity(intent);
                            } catch (Exception e) {
                                Timber.tag(TAG).e( "Failed to open TempCallActivity: " + e.getMessage());
                            }
                        } else if (code == 0) {
                            // 退出临时呼叫 → 关闭临时呼叫页面
                            if (com.stand.standapp.TempCallActivity.isOpen()) {
                                com.stand.standapp.TempCallActivity.closeWithMessage("临时呼叫已结束");
                            } else if (com.stand.standapp.TempCallActivity.isMinimizedState()) {
                                // 最小化状态下收到结束消息，清除状态并通知前端
                                com.stand.standapp.TempCallActivity.clearMinimizedState();
                            }
                        } else if (code == 2) {
                            // 呼叫失败 → 关闭临时呼叫页面
//                            if (com.stand.standapp.TempCallActivity.isOpen()) {
//                                com.stand.standapp.TempCallActivity.closeWithMessage("呼叫失败");
//                            } else if (com.stand.standapp.TempCallActivity.isMinimizedState()) {
//                                // 最小化状态下收到失败消息，清除状态并通知前端
//                                com.stand.standapp.TempCallActivity.clearMinimizedState();
//                            }
                        }
                    }
                    break;

                case "86"://用户进入群组信息通知
                    String userGroupId = lisHex.get(2) + "" + lisHex.get(3) + "" + lisHex.get(4) + "" + lisHex.get(5);
                    List<String> stringsJumpGroup = new ArrayList<>();
                    try {
                        int numA = 6;
                        int numB = 7;

                        int size = lisHex.size() - 6;
                        size = (size / 2) - 1;
                        for (int i = 0; i < size; i++) {
                            if (i == 0) {
                                stringsJumpGroup.add(ngx + lisHex.get(i + numB) + "" + lisHex.get(i + numA));
                            } else {
                                int start = i + numB;
                                int end = i + numB + 1;
                                stringsJumpGroup.add(ngx + lisHex.get(end) + "" + lisHex.get(start));
                                numB = numB + 1;
                            }

                        }

                    } catch (Exception e) {
                        Timber.tag(TAG).e(e, "Decode hex failed");
                    } finally {
                        String userGroupName = "";
                        for (int i = 0; i < stringsJumpGroup.size(); i++) {
                            userGroupName += unicode(stringsJumpGroup.get(i));
                        }
                        Timber.tag(TAG).i("进入群组 " + userGroupName);
                        indexGroupId = userGroupId;
                        indexGroupName = userGroupName;
                        CallBackUtil.callBackNotifyUpdateGroup(userGroupId, userGroupName);
                    }
                    break;

                case "8d"://用户定位信息通知
                    if (lisHex.get(1).equals("00")) {

                        String str = "";
                        String locationMemberId = lisHex.get(2) + "" + lisHex.get(3) + "" + lisHex.get(4) + "" + lisHex.get(5);

                        for (int i = 0; i < lisHex.size() - 1; i++) {
                            if (i > 5) {
                                str = str + "" + lisHex.get(i).toString();
                            }
                        }
                        String address = hexString2String(str);
                        address = address.substring(0,address.lastIndexOf(":"));
                        try {
                            String[] strLis = address.split(",");
                            double latitude = Double.parseDouble(strLis[1]);
                            double longitude = Double.parseDouble(strLis[0]);
                            String time = strLis[2];
                            CallBackUtil.callBackNotifyLocationStatus(0, locationMemberId, latitude, longitude, time);
                        } catch (Exception e) {
                            Timber.tag(TAG).e( "获取定位Exception-->" + e.getMessage());
                        }
                    } else {
                        CallBackUtil.callBackNotifyLocationStatus(1, "", 0.0, 0.0, "");
                    }
                    break;

                case "11"://上报位置信息
                    CallBackUtil.callBackNotifyUploadLocation(errorNum.equals("00")? true : false);
                    break;

                case "02"://获取写码账号信息
                    String str = "";
                    for (int i = 4; i < lisHex.size() - 2; i++) {
                        str = str + "" + lisHex.get(i);
                    }
                    String cmdTxt = hexString2String(str);
                    CallBackUtil.callBackNotifyCodeInfo(cmdTxt);
                    break;

                case "48"://获取写码密码信息
                    String strPwd = "";
                    for (int i = 4; i < lisHex.size() - 2; i++) {
                        strPwd = strPwd + "" + lisHex.get(i);
                    }
                    String cmdPwdTxt = hexString2String(strPwd);
                    CallBackUtil.callBackNotifyPwdInfo(cmdPwdTxt);
                    break;

                case "45"://进入写码模式通知
                    CallBackUtil.callBackNotifyCodeOpenStatus(errorNum.equals("00")? true : false);
                    break;

                case "52"://退出写码模式操作
                    CallBackUtil.callBackNotifyCodeExiteStatus(errorNum.equals("00")? true : false);
                    break;

                case "47"://上传经销商密码
                    CallBackUtil.callBackNotifyUploadAgentPwd(errorNum.equals("00")? true : false);
                    break;

                case "53"://上报本机告警信号
                    CallBackUtil.callBackRequestReportAlarm(errorNum.equals("00")? true : false);
                    break;

                case "54"://停止本机告警信号
                    CallBackUtil.callBackRequestStopAlarm(errorNum.equals("00")? true : false);
                    break;

                case "8e"://收到群成员告警信号
                    if (lisHex.get(1).equals("00")) {
                        List<String> strName = new ArrayList<>();
                        double latitude = 0.0, longitude = 0.0;
                        try {
                            String string = "";
                            for (int i = 4; i < lisHex.size(); i++) {
                                string += lisHex.get(i).toString();
                            }
                            String address = hexString2String(string);
                            Timber.tag(TAG).i( "address-->" + address);

                            String[] strLis = address.split(",");
                            latitude = Double.parseDouble(strLis[0]);
                            longitude = Double.parseDouble(strLis[1]);
                            int size = lisHex.size() - (8 + strLis[0].length() + strLis[1].length());
                            size = size / 2;
                            int numA = 4 + strLis[0].length() + strLis[1].length() + 3;
                            int numB = 4 + strLis[0].length() + strLis[1].length() + 4;
                            for (int i = 0; i < size; i++) {
                                if (i == 0) {
                                    strName.add(ngx + lisHex.get(i + numB) + "" + lisHex.get(i + numA));
                                } else {
                                    int start = i + numB;
                                    int end = i + numB + 1;
                                    strName.add(ngx + lisHex.get(end) + "" + lisHex.get(start));
                                    numB = numB + 1;
                                }
                            }

                        } catch (Exception e) {

                        } finally {
                            String tempTxt = "";
                            for (int i = 0; i < strName.size(); i++) {
                                if (strName.get(i).equals("\\u0000")) break;
                                tempTxt += unicode(strName.get(i));
                            }
                            CallBackUtil.callBackEnotifyAlarm(tempTxt, latitude, longitude);
                        }
                    }
                    break;

                case "8f"://收到群成员停止警告信息
                    CallBackUtil.callBackEnotifyStopAlarm();
                    break;

                case "78"://上传NFC信息
                    CallBackUtil.callBackRequestNfc(errorNum.equals("00")? true : false);
                    break;
            }
        }catch (Exception e){
            Timber.tag(TAG).e("at_OEM_AT_cb Exception " + e.getMessage());
        }

    }

    /**
     * 判断登录状态冲突, 1min内超过5次状态切换则视为登录冲突
     * state
     * 0 : 离线
     * 1 : 登陆中
     * 2 : 登陆成功
     * 3 : 注销中
     * 说明：第一次登录 通知状态 先01再02，
     * 离线再上线 通知状态 先00再01
     * tip：1min内会出现40次左右0-1切换
     */
    public static boolean isLoginConflict(String state) {
        Timber.tag(TAG).d( " isLoginConflict state: " + state + ",oldLoginSate: " + oldLoginSate + ", logNum: " + logNum);
        if (oldLoginSate.equals("00") && state.equals("01")) {
            Timber.tag(TAG).d( "isLoginConflict first login...");
            logNum++;
            oldLoginSate = state;
        } else if (oldLoginSate.equals("01") && state.equals("00")) {
            Timber.tag(TAG).d( "isLoginConflict login state changed...");
            logNum++;
            oldLoginSate = state;
        }
        if (1 == logNum) {
            offlineTime = System.currentTimeMillis();
        }
        Timber.tag(TAG).d( "isLoginConflict logNum: " + logNum + ", offlineTime: " + offlineTime);
        if (System.currentTimeMillis() - offlineTime <= 60 * 1000) {
            if (logNum > 5) {
                Timber.tag(TAG).d("isLoginConflict login state changed: " + logNum + " in 1min");
                return true;
            }
        } else {
            Timber.tag(TAG).d("isLoginConflict maybe network change, reset...");
            logNum = 0;
            offlineTime = System.currentTimeMillis();
            return false;
        }
        return false;
    }

    public static void at_Play_TTS_cb(String sData){
        try {
            String[] txt = sData.split("\"");
            String data = txt[1];
            Timber.tag(TAG).d( "at_Play_TTS_cb sData: " + sData);

            String ngx = "\\u";
            List<String> strings = new ArrayList<>();

            try {
                String str = "";
                for (int i = 0; i < data.length(); i++) {
                    if (i == 0) {
                        str = ngx + data.charAt(i);
                    } else if (i % 4 == 0) {
                        strings.add(str);
                        str = ngx + data.charAt(i);

                    } else if (i == data.length() - 1) {
                        str = str + data.charAt(i);
                        strings.add(str);
                    } else {
                        str = str + data.charAt(i);
                    }

                }

            } catch (Exception e) {
                Timber.tag(TAG).e(e, "Decode hex failed");
            } finally {
                StringBuilder sb = new StringBuilder();
                for (int k = 0; k < strings.size(); k++) {
                    sb.append(unicode(strings.get(k)));
                }
                String tempTxt = sb.toString();
                Timber.tag(TAG).i("at_Play_TTS_cb " + tempTxt);
                if (tempTxt.contains("已登录")) {
                    String showName = tempTxt.substring(3, tempTxt.length());
                    CallBackUtil.callBackLogin(true, showName);
                    ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
                    Runnable task = () -> {
                        Timber.tag(TAG).d( "callBackLogin send tcp and udp");
                        SendAtUtil.sendUDP();
                        SendAtUtil.sendTCP();
                    };
                    executor.scheduleAtFixedRate(task, 0, 40, TimeUnit.SECONDS);
                } else if (tempTxt.contains("账号已更新")) {
                    Timber.tag(TAG).w("TTS reports account updated: '%s'", tempTxt);
                } else if (tempTxt.contains("账号或密码错误")) {
                    CallBackUtil.callBackLogin(false, "");
                    Timber.tag(TAG).e("Account/password error, showing dialog. TTS: '%s'", tempTxt);
                    com.stand.standapp.MainActivity.showPttUpdateDialog("您的 PTT 账号信息账号或密码错误。\n请点击确认重启应用。","账号或密码错误");
                }else if (tempTxt.contains("请配置账号")) {
                    Timber.tag(TAG).w("TTS reports no account configured: '%s'", tempTxt);
                }

            }
        } catch (Exception e) {
            Timber.tag(TAG).e(e, "Decode hex failed");
        }
    }


    public static String unicode(String str) {

        Pattern pattern = Pattern.compile("(\\\\u(\\p{XDigit}{4}))");
        Matcher matcher = pattern.matcher(str);
        char ch;
        while (matcher.find()) {
            String group = matcher.group(2);
            ch = (char) Integer.parseInt(group, 16);
            String group1 = matcher.group(1);
            str = str.replace(group1, ch + "");
        }
        return str;
    }

    public static String unicodeToString(String hex) {
        int t = hex.length() / 6;
        StringBuilder str = new StringBuilder();
        for (int i = 0; i < t; i++) {
            String s = hex.substring(i * 6, (i + 1) * 6);
            // 高位需要补上00再转
            String s1 = s.substring(2, 4) + "00";
            // 低位直接转
            String s2 = s.substring(4);
            // 将16进制的string转为int
            int n = Integer.valueOf(s1, 16) + Integer.valueOf(s2, 16);
            // 将int转换为字符
            char[] chars = Character.toChars(n);
            str.append(new String(chars));
        }
        return str.toString();
    }

    public static String hexString2String(String src) {
        String temp = "";
        for (int i = 0; i < src.length() / 2; i++) {
            temp = temp + (char) Integer.valueOf(src.substring(i * 2, i * 2 + 2), 16).byteValue();
        }
        return temp;
    }
}
