package Common.Alarm;

import SdkService.AlarmService.HCISUPAlarm;
import Common.CommonMethod;
import com.sun.jna.Native;
import com.sun.jna.Pointer;

/**
 * @author zhengxiaohui
 * @date 2023/8/14 11:45
 * @desc 告警事件处理函数
 */
public class AlarmEventHandle {

    public static void processAlarmData(int dwAlarmType, Pointer pStru, int dwStruLen, Pointer pXml, int dwXmlLen, Pointer pUrl, int dwUrlLen) {
        if (pUrl != Pointer.NULL) {
            dwAlarmType = HCISUPAlarm.EHOME_ISAPI_ALARM;
        }

        switch (dwAlarmType) {
            // Ehome基本报警
            case HCISUPAlarm.EHOME_ALARM: {
                processEhomeAlarm(dwAlarmType, pStru, dwStruLen, pXml, dwXmlLen);
                break;
            }
            // 热度图报告
            case HCISUPAlarm.EHOME_ALARM_HEATMAP_REPORT: {
                processEhomeAlarmHeatMapReport(pStru, dwStruLen, pXml, dwXmlLen);
                break;
            }
            // 人脸抓拍报告
            case HCISUPAlarm.EHOME_ALARM_FACESNAP_REPORT: {
                processEhomeFaceSnapReport(pStru, dwStruLen, pXml, dwXmlLen);
                break;
            }
            // GPS信息上传
            case HCISUPAlarm.EHOME_ALARM_GPS: {
                processEhomeGps(pStru, dwStruLen, pXml, dwXmlLen);
                break;
            }
            // 报警主机CID告警上传
            case HCISUPAlarm.EHOME_ALARM_CID_REPORT: {
                processEhomeCIDReport(pStru, dwStruLen, pXml, dwXmlLen);
                break;
            }
            // 图片URL上报
            case HCISUPAlarm.EHOME_ALARM_NOTICE_PICURL: {
                processEhomeAlarmNoticPicUrl(pStru, dwStruLen, pXml, dwXmlLen);
                break;
            }
            // 异步失败通知
            case HCISUPAlarm.EHOME_ALARM_NOTIFY_FAIL: {
                processEhomeNotifyFail(pStru, dwStruLen, pXml, dwXmlLen);
                break;
            }
            // 门禁事件上报
            case HCISUPAlarm.EHOME_ALARM_ACS: {
                processEhomeAlarmAcs(pStru, dwStruLen);
                break;
            }
            // 无线网络信息上传
            case HCISUPAlarm.EHOME_ALARM_WIRELESS_INFO: {
                processAlarmWirelessInfo(pStru, dwStruLen, pXml, dwXmlLen);
                break;
            }
            // ISAPI报警上传
            case HCISUPAlarm.EHOME_ISAPI_ALARM: {
                processEhomeIsapiAlarm(pStru, dwStruLen, pUrl, dwUrlLen);
                break;
            }
            // 车载设备的客流数据
            case HCISUPAlarm.EHOME_ALARM_MPDCDATA: {
                processEhomeAlarmMpdcData(pStru, dwStruLen, pXml, dwXmlLen);
                break;
            }
            // 二维码报警上传
            case HCISUPAlarm.EHOME_ALARM_QRCODE: {
                processEhomeAlarmQrcode(pXml, dwXmlLen);
                break;
            }
            // 人脸测温报警上传
            case HCISUPAlarm.EHOME_ALARM_FACETEMP: {
                processEhomeAlarmFaceTemp(pXml, dwXmlLen);
                break;
            }
            default: {
                System.out.println("unknown_Alarm_type: " + dwAlarmType);
            }
        }
    }

    /**
     * Ehome基本报警
     *
     * @param pStru
     * @param dwStruLen
     * @param pXml
     * @param dwXmlLen
     */
    public static void processEhomeAlarm(int alarmType, Pointer pStru, int dwStruLen, Pointer pXml, int dwXmlLen) {
        HCISUPAlarm.NET_EHOME_ALARM_INFO ehomeAlarmInfo = new HCISUPAlarm.NET_EHOME_ALARM_INFO();
        ehomeAlarmInfo.write();
        Pointer pEhomeAlarmInfo = ehomeAlarmInfo.getPointer();
        pEhomeAlarmInfo.write(0, pStru.getByteArray(0, ehomeAlarmInfo.size()), 0, ehomeAlarmInfo.size());
        ehomeAlarmInfo.read();

        System.out.println("[ALARM]DeviceID:" + Native.toString(ehomeAlarmInfo.szDeviceID)
                + ",Time:" + Native.toString(ehomeAlarmInfo.szAlarmTime)
                + ",Type:" + ehomeAlarmInfo.dwAlarmType
                + ",Action:" + ehomeAlarmInfo.dwAlarmAction
                + ",Channel:" + ehomeAlarmInfo.dwVideoChannel
                + ",AlarmIn:" + ehomeAlarmInfo.dwAlarmInChannel
                + ",DiskNo:" + ehomeAlarmInfo.dwDiskNumber);

        switch (alarmType) {
            case HCISUPAlarm.ALARM_TYPE_DEV_CHANGED_STATUS: {
                System.out.println("[ALARM_TYPE_DEV_CHANGED_STATUS]byDeviceStatus:" + ehomeAlarmInfo.uStatusUnion.struDevStatusChanged.byDeviceStatus);
                break;
            }
            case HCISUPAlarm.ALARM_TYPE_CHAN_CHANGED_STATUS: {
                System.out.println("[ALARM_TYPE_CHAN_CHANGED_STATUS]byChanStatus:" + ehomeAlarmInfo.uStatusUnion.struChanStatusChanged.byChanStatus
                        + ",wChanNO:" + ehomeAlarmInfo.uStatusUnion.struChanStatusChanged.wChanNO);
                break;
            }
            case HCISUPAlarm.ALARM_TYPE_HD_CHANGED_STATUS: {
                System.out.println("[ALARM_TYPE_HD_CHANGED_STATUS]byHDStatus:" + ehomeAlarmInfo.uStatusUnion.struHdStatusChanged.byHDStatus
                        + ",wHDNo:" + ehomeAlarmInfo.uStatusUnion.struHdStatusChanged.wHDNo
                        + ",dwVolume:" + ehomeAlarmInfo.uStatusUnion.struHdStatusChanged.dwVolume);
                break;
            }
            case HCISUPAlarm.ALARM_TYPE_DEV_TIMING_STATUS: {
                System.out.println("[ALARM_TYPE_DEV_TIMING_STATUS]byCPUUsage:%d" + ehomeAlarmInfo.uStatusUnion.struDevTimeStatus.byCPUUsage +
                        ",byMainFrameTemp:%d" + ehomeAlarmInfo.uStatusUnion.struDevTimeStatus.byMainFrameTemp +
                        ",byBackPanelTemp:%d" + ehomeAlarmInfo.uStatusUnion.struDevTimeStatus.byBackPanelTemp +
                        ",dwMemoryTotal:%d" + ehomeAlarmInfo.uStatusUnion.struDevTimeStatus.dwMemoryTotal +
                        ",dwMemoryUsage:%d" + ehomeAlarmInfo.uStatusUnion.struDevTimeStatus.dwMemoryUsage);
                break;
            }
            case HCISUPAlarm.ALARM_TYPE_CHAN_TIMING_STATUS: {
                System.out.println("[ALARM_TYPE_CHAN_TIMING_STATUS]byLinkNum:%d" + ehomeAlarmInfo.uStatusUnion.struChanTimeStatus.byLinkNum +
                        ",wChanNO:%d" + ehomeAlarmInfo.uStatusUnion.struChanTimeStatus.wChanNO +
                        ",dwBitRate:%d" + ehomeAlarmInfo.uStatusUnion.struChanTimeStatus.dwBitRate);
                break;
            }
            case HCISUPAlarm.ALARM_TYPE_HD_TIMING_STATUS: {
                System.out.println("[ALARM_TYPE_HD_TIMING_STATUS]wHDNo:%d" + ehomeAlarmInfo.uStatusUnion.struHdTimeStatus.wHDNo +
                        ",dwHDFreeSpace:%d" + ehomeAlarmInfo.uStatusUnion.struHdTimeStatus.dwHDFreeSpace);
                break;
            }
            default: {
                break;
            }
        }
    }

    /**
     * 热度图报告
     *
     * @param pStru
     * @param dwStruLen
     * @param pXml
     * @param dwXmlLen
     */
    public static void processEhomeAlarmHeatMapReport(Pointer pStru, int dwStruLen, Pointer pXml, int dwXmlLen) {
        if (pStru == Pointer.NULL) {
            return;
        }
        HCISUPAlarm.NET_EHOME_HEATMAP_REPORT struHeatMapReport = new HCISUPAlarm.NET_EHOME_HEATMAP_REPORT();
        struHeatMapReport.write();
        Pointer pStruHeatMapReport = struHeatMapReport.getPointer();
        pStruHeatMapReport.write(0, pStru.getByteArray(0, struHeatMapReport.size()), 0, struHeatMapReport.size());
        struHeatMapReport.read();

        System.out.println("[HEATMAPREPORT]DeviceID: " + Native.toString(struHeatMapReport.byDeviceID) +
                ",Channel:%d" + struHeatMapReport.dwVideoChannel +
                ",Start:%s" + Native.toString(struHeatMapReport.byStartTime) +
                ",Stop:%s" + Native.toString(struHeatMapReport.byStopTime) +
                ",HeatMapValue:" + struHeatMapReport.struHeatmapValue.dwMaxHeatMapValue
                + "  " + struHeatMapReport.struHeatmapValue.dwMinHeatMapValue
                + "  " + struHeatMapReport.struHeatmapValue.dwTimeHeatMapValue +
                ",Size:" + struHeatMapReport.struPixelArraySize.dwLineValue
                + "  " + struHeatMapReport.struPixelArraySize.dwColumnValue);
    }


    /**
     * 人脸抓拍报告
     *
     * @param pStru
     * @param dwStruLen
     * @param pXml
     * @param dwXmlLen
     */
    public static void processEhomeFaceSnapReport(Pointer pStru, int dwStruLen, Pointer pXml, int dwXmlLen) {
        if (pStru == Pointer.NULL) {
            return;
        }
        HCISUPAlarm.NET_EHOME_FACESNAP_REPORT struFaceSnapReport = new HCISUPAlarm.NET_EHOME_FACESNAP_REPORT();
        struFaceSnapReport.write();
        Pointer pStruFaceSnapReport = struFaceSnapReport.getPointer();
        pStruFaceSnapReport.write(0, pStru.getByteArray(0, struFaceSnapReport.size()), 0, struFaceSnapReport.size());
        struFaceSnapReport.read();

        System.out.println("[FACESNAPREPORT]DeviceID: " + Native.toString(struFaceSnapReport.byDeviceID) +
                ",Channel:" + struFaceSnapReport.dwVideoChannel +
                ",Time:" + Native.toString(struFaceSnapReport.byAlarmTime) +
                ",PicID:" + struFaceSnapReport.dwFacePicID +
                ",Score:" + struFaceSnapReport.dwFaceScore +
                ",TargetID:" + struFaceSnapReport.dwTargetID +
                ",Target Zone[" +
                " " + struFaceSnapReport.struTarketZone.dwX +
                " " + struFaceSnapReport.struTarketZone.dwY +
                " " + struFaceSnapReport.struTarketZone.dwWidth +
                " " + struFaceSnapReport.struTarketZone.dwHeight +
                "]" +
                ",FacePicZone[" +
                " " + struFaceSnapReport.struFacePicZone.dwX +
                " " + struFaceSnapReport.struFacePicZone.dwY +
                " " + struFaceSnapReport.struFacePicZone.dwWidth +
                " " + struFaceSnapReport.struFacePicZone.dwHeight +
                "]" +
                ",HumanFeature:[" +
                " " + struFaceSnapReport.struHumanFeature.byAgeGroup +
                " " + struFaceSnapReport.struHumanFeature.bySex +
                " " + struFaceSnapReport.struHumanFeature.byEyeGlass +
                " " + struFaceSnapReport.struHumanFeature.byMask +
                " " +
                "]" +
                ",Duration:" + struFaceSnapReport.dwStayDuration +
                ",FacePicLen:" + struFaceSnapReport.dwFacePicLen +
                ",BackGroundPicLen:" + struFaceSnapReport.dwBackgroudPicLen
        );
    }

    /**
     * GPS信息上传
     *
     * @param pStru
     * @param dwStruLen
     * @param pXml
     * @param dwXmlLen
     */
    public static void processEhomeGps(Pointer pStru, int dwStruLen, Pointer pXml, int dwXmlLen) {
        if (pStru == Pointer.NULL) {
            return;
        }
        HCISUPAlarm.NET_EHOME_GPS_INFO struGps = new HCISUPAlarm.NET_EHOME_GPS_INFO();
        struGps.write();
        Pointer pStr = struGps.getPointer();
        pStr.write(0, pStru.getByteArray(0, struGps.size()), 0, struGps.size());
        struGps.read();

        System.out.println("[GPS]DeviceID:" + Native.toString(struGps.byDeviceID) +
                ",SampleTime:" + Native.toString(struGps.bySampleTime) +
                ",Division:[" +
                "" + struGps.byDivision[0] +
                " " + struGps.byDivision[1] +
                "]" +
                ",Satelites:" + struGps.bySatelites +
                ",Precision:" + struGps.byPrecision +
                ",Longitude:" + struGps.dwLongitude +
                ",Latitude:" + struGps.dwLatitude +
                ",Direction:" + struGps.dwDirection +
                ",Speed:" + struGps.dwSpeed +
                ",Height:" + struGps.dwHeight);
    }

    /**
     * 报警主机CID告警上传
     *
     * @param pStru
     * @param dwStruLen
     * @param pXml
     * @param dwXmlLen
     */
    public static void processEhomeCIDReport(Pointer pStru, int dwStruLen, Pointer pXml, int dwXmlLen) {
        if (pStru == Pointer.NULL) {
            return;
        }
        HCISUPAlarm.NET_EHOME_CID_INFO strCidInfo = new HCISUPAlarm.NET_EHOME_CID_INFO();
        HCISUPAlarm.NET_EHOME_CID_INFO_INTERNAL_EX strCidInfoEx = new HCISUPAlarm.NET_EHOME_CID_INFO_INTERNAL_EX();
        HCISUPAlarm.NET_EHOME_CID_INFO_PICTUREINFO_EX strPicInfoEx = new HCISUPAlarm.NET_EHOME_CID_INFO_PICTUREINFO_EX();

        strCidInfo.write();
        Pointer pStrCidInfo = strCidInfo.getPointer();
        pStrCidInfo.write(0, pStru.getByteArray(0, strCidInfo.size()), 0, strCidInfo.size());
        strCidInfo.read();

        strCidInfoEx.write();
        Pointer pStrCidInfoEx = strCidInfoEx.getPointer();
        pStrCidInfoEx.write(0, strCidInfo.pCidInfoEx.getByteArray(0, strCidInfoEx.size()), 0, strCidInfoEx.size());
        strCidInfoEx.read();

        strPicInfoEx.write();
        Pointer pStrPicInfoEx = strPicInfoEx.getPointer();
        pStrPicInfoEx.write(0, strCidInfo.pPicInfoEx.getByteArray(0, strPicInfoEx.size()), 0, strPicInfoEx.size());
        strPicInfoEx.read();

        String cDescribe = Native.toString(strCidInfo.byCIDDescribe);
        String uuid = null;
        System.out.println("cDescribe: " + cDescribe);

        // 有拓展字段则处理拓展字段信息
        if (strCidInfo.byExtend == 1) {
            cDescribe = Native.toString(strCidInfoEx.byCIDDescribeEx);
            uuid = Native.toString(strCidInfoEx.byUUID);
            System.out.println("[CID_EX]uuid[" + Native.toString(strCidInfoEx.byUUID) + "]" +
                    ",recheck[" + strCidInfoEx.byRecheck + "]" +
                    ",Recheck URL[" + Native.toString(strCidInfoEx.byVideoURL) + "]" +
                    ",videoType[" + Native.toString(strCidInfoEx.byVideoType) + "]");
            for (int i = 0; i < HCISUPAlarm.MAX_PICTURE_NUM; i++) {
                if ((strCidInfoEx.byRecheck == 1) && (strPicInfoEx.byPictureURL[i][0]) != '\0') {
                    System.out.println("[CID_EX]uuid[" + Native.toString(strCidInfoEx.byUUID) + "]" +
                            ",recheck[" + strCidInfoEx.byRecheck + "]" +
                            ",PicURL[" + Native.toString(strPicInfoEx.byPictureURL[i]) + "]");
                }
            }

            StringBuilder LinkedSubSystem = new StringBuilder();
            for (int i = 0; i < HCISUPAlarm.MAX_SUBSYSTEM_LEN; i++) {
                if (strCidInfoEx.byLinkageSubSystem[i] > 0)//关联子系统最小值为1
                {
                    LinkedSubSystem.append(strCidInfoEx.byLinkageSubSystem[i]);
                }
            }
            System.out.println("[CID_EX] All Linked SubSystem: " + LinkedSubSystem);
        }

        System.out.println("[CID]uuid[%s]" + uuid +
                ",DeviceID:%s" + Native.toString(strCidInfo.byDeviceID) +
                ",CID code:%d" + strCidInfo.dwCIDCode +
                ",CID type:%d" + strCidInfo.dwCIDType +
                ",Subsys No:%d" + strCidInfo.dwSubSysNo +
                ",Describe:%s" + cDescribe +
                ",TriggerTime:%s" + Native.toString(strCidInfo.byTriggerTime) +
                ",UploadTime:%s" + Native.toString(strCidInfo.byUploadTime) +
                ",CID param[" +
                "  " + strCidInfo.struCIDParam.dwUserType +
                "  " + strCidInfo.struCIDParam.lUserNo +
                "  " + strCidInfo.struCIDParam.lZoneNo +
                "  " + strCidInfo.struCIDParam.lKeyboardNo +
                "  " + strCidInfo.struCIDParam.lVideoChanNo +
                "  " + strCidInfo.struCIDParam.lDiskNo +
                "  " + strCidInfo.struCIDParam.lModuleAddr +
                //UTF-8转GBK
                "  " + CommonMethod.UTF8toGBKStr(strCidInfo.struCIDParam.byUserName) +
                "]");
    }

    /**
     * 图片URL上报
     *
     * @param pStru
     * @param dwStruLen
     * @param pXml
     * @param dwXmlLen
     */
    public static void processEhomeAlarmNoticPicUrl(Pointer pStru, int dwStruLen, Pointer pXml, int dwXmlLen) {
        // TODO 这里添加打印信息的处理逻辑
    }

    /**
     * 异步失败通知
     *
     * @param pStru
     * @param dwStruLen
     * @param pXml
     * @param dwXmlLen
     */
    public static void processEhomeNotifyFail(Pointer pStru, int dwStruLen, Pointer pXml, int dwXmlLen) {
        // TODO 这里添加打印信息的处理逻辑
    }

    /**
     * 门禁事件上报
     *
     * @param pStru
     * @param dwStruLen
     */
    public static void processEhomeAlarmAcs(Pointer pStru, int dwStruLen) {
        // TODO 这里添加打印信息的处理逻辑
    }

    /**
     * 无线网络信息上传
     *
     * @param pStru
     * @param dwStruLen
     * @param pXml
     * @param dwXmlLen
     */
    public static void processAlarmWirelessInfo(Pointer pStru, int dwStruLen, Pointer pXml, int dwXmlLen) {
        // TODO 这里添加打印信息的处理逻辑
    }

    /**
     * ISAPI报警上传
     *
     * @param pStru
     * @param dwStruLen
     * @param pUrl
     * @param dwUrlLen
     */
    public static void processEhomeIsapiAlarm(Pointer pStru, int dwStruLen, Pointer pUrl, int dwUrlLen) {
        if (pUrl != Pointer.NULL && dwUrlLen > 0) {
            // ISUP4.0事件上报，默认报警与图片数据不分离，此时返回的url不为空，这种情况增加下demo打印
            // 分离后的数据，url字段不为空
            System.out.println("ISAPI报警上传, ISAPI Alarm");
            return;
        }

        if (pStru == Pointer.NULL) {
            return;
        }

        HCISUPAlarm.NET_EHOME_ALARM_ISAPI_INFO strISAPIAlarm = new HCISUPAlarm.NET_EHOME_ALARM_ISAPI_INFO();
        strISAPIAlarm.write();
        Pointer pISAPIAlarm = strISAPIAlarm.getPointer();
        pISAPIAlarm.write(0, pStru.getByteArray(0, strISAPIAlarm.size()), 0, strISAPIAlarm.size());
        strISAPIAlarm.read();

        if (strISAPIAlarm.pAlarmData != Pointer.NULL) {
            String alarmData = null;
            // 判断报警数据的格式
            if (strISAPIAlarm.byDataType != 0) { // 1: xml格式数据 2：json格式数据
                HCISUPAlarm.BYTE_ARRAY m_strISAPIData = new HCISUPAlarm.BYTE_ARRAY(strISAPIAlarm.dwAlarmDataLen);
                m_strISAPIData.write();
                Pointer pPlateInfo = m_strISAPIData.getPointer();
                pPlateInfo.write(0, strISAPIAlarm.pAlarmData.getByteArray(0, m_strISAPIData.size()), 0, m_strISAPIData.size());
                m_strISAPIData.read();

                alarmData = new String(m_strISAPIData.byValue).trim();
                System.out.println("alarmData:\n" + alarmData);
            }
        }
    }

    /**
     * 车载设备的客流数据
     *
     * @param pStru
     * @param dwStruLen
     * @param pXml
     * @param dwXmlLen
     */
    public static void processEhomeAlarmMpdcData(Pointer pStru, int dwStruLen, Pointer pXml, int dwXmlLen) {
        // TODO 这里添加打印信息的处理逻辑
    }

    /**
     * 二维码报警上传
     *
     * @param pXml
     * @param dwXmlLen
     */
    public static void processEhomeAlarmQrcode(Pointer pXml, int dwXmlLen) {
        // TODO 这里添加打印信息的处理逻辑
    }

    /**
     * 人脸测温报警上传
     *
     * @param pXml
     * @param dwXmlLen
     */
    public static void processEhomeAlarmFaceTemp(Pointer pXml, int dwXmlLen) {
        // TODO 这里添加打印信息的处理逻辑
    }

}
