package com.usky.sas.common.hik.sdk;

import com.usky.sas.common.hik.HikNvrChannelInfo;
import com.usky.sas.common.hik.OsSelect;
import com.usky.sas.common.hik.sdk.HCNetSDK.NET_DVR_COMPRESSIONCFG_V30;
import com.usky.sas.common.hik.sdk.HCNetSDK.NET_DVR_COMPRESSION_INFO_V30;
import com.usky.sas.common.hik.sdk.HCNetSDK.NET_DVR_DEVICEINFO_V40;
import com.usky.sas.common.hik.sdk.HCNetSDK.NET_DVR_IPCHANINFO;
import com.usky.sas.common.hik.sdk.HCNetSDK.NET_DVR_IPPARACFG_V40;
import com.usky.sas.common.hik.sdk.HCNetSDK.NET_DVR_USER_LOGIN_INFO;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class InitHCNetSDK {
    private static final Logger log = LoggerFactory.getLogger(InitHCNetSDK.class);
    public static Map<String, HCNetSDK> hikSDKHashMap = new ConcurrentHashMap();
    public static HCNetSDK hCNetSDK;

    public InitHCNetSDK() {
    }

    private static boolean createSDKInstance() {
        if (hCNetSDK == null) {
            Class var0 = HCNetSDK.class;
            synchronized(HCNetSDK.class) {
                String strDllPath = "";

                try {
                    if (OsSelect.isWindows()) {
                        strDllPath = "C:\\Users\\41932\\Desktop\\hik\\libs\\HCNetSDK.dll";
                    } else if (OsSelect.isLinux()) {
                        strDllPath = "/www/wwwroot/fjkjagapp.fj724.com/HikSDK/sdk/libhcnetsdk.so";
                    }

                    hCNetSDK = (HCNetSDK)Native.loadLibrary(strDllPath, HCNetSDK.class);
                    log.info("初始化HCNetSDK成功============");
                    hCNetSDK.NET_DVR_Init();
                    hCNetSDK.NET_DVR_SetConnectTime(2000, 1);
                    hCNetSDK.NET_DVR_SetReconnect(10000, true);
                    hikSDKHashMap.put("hCNetSDK", hCNetSDK);
                    hCNetSDK.NET_DVR_SetLogToFile(3, "./hikSdkLog", false);
                } catch (Exception var4) {
                    System.out.println("loadLibrary: " + strDllPath + " Error: " + var4.getMessage());
                    return false;
                }
            }
        }

        return true;
    }

    public static int loginDevice(String ip, short port, String user, String psw) {
        log.info("设备登录：{}", ip);
        NET_DVR_USER_LOGIN_INFO loginInfo = new NET_DVR_USER_LOGIN_INFO();
        NET_DVR_DEVICEINFO_V40 deviceInfo = new NET_DVR_DEVICEINFO_V40();
        byte[] deviceAddress = new byte[129];
        byte[] ipBytes = ip.getBytes();
        System.arraycopy(ipBytes, 0, deviceAddress, 0, Math.min(ipBytes.length, deviceAddress.length));
        loginInfo.sDeviceAddress = deviceAddress;
        byte[] userName = new byte[64];
        byte[] password = psw.getBytes();
        System.arraycopy(user.getBytes(), 0, userName, 0, Math.min(user.length(), userName.length));
        System.arraycopy(password, 0, loginInfo.sPassword, 0, Math.min(password.length, loginInfo.sPassword.length));
        loginInfo.sUserName = userName;
        loginInfo.wPort = port;
        loginInfo.bUseAsynLogin = false;
        loginInfo.byLoginMode = 0;
        int userID = hCNetSDK.NET_DVR_Login_V40(loginInfo, deviceInfo);
        if (userID == -1) {
            log.error("登录失败，错误码为: " + hCNetSDK.NET_DVR_GetLastError());
        } else {
            log.info(ip + " 设备登录成功！");
            int startDChan = deviceInfo.struDeviceV30.byStartDChan;
            log.info("预览起始通道号: " + startDChan);
        }

        return userID;
    }

    public static Integer getIPChannelInfo(Integer userID, String ipAddr) {
        IntByReference ibrBytesReturned = new IntByReference(0);
        NET_DVR_IPPARACFG_V40 m_strIpparaCfg = new NET_DVR_IPPARACFG_V40();
        m_strIpparaCfg.write();
        Pointer lpIpParaConfig = m_strIpparaCfg.getPointer();
        hCNetSDK.NET_DVR_GetDVRConfig(userID, 1062, 0, lpIpParaConfig, m_strIpparaCfg.size(), ibrBytesReturned);
        m_strIpparaCfg.read();
        log.info("起始数字通道号：" + m_strIpparaCfg.dwStartDChan);

        for(int iChannum = 0; iChannum < m_strIpparaCfg.dwDChanNum; ++iChannum) {
            int channum = iChannum + m_strIpparaCfg.dwStartDChan;
            m_strIpparaCfg.struStreamMode[iChannum].read();
            if (m_strIpparaCfg.struStreamMode[iChannum].byGetStreamType == 0) {
                m_strIpparaCfg.struStreamMode[iChannum].uGetStream.setType(NET_DVR_IPCHANINFO.class);
                m_strIpparaCfg.struStreamMode[iChannum].uGetStream.struChanInfo.read();
                if (m_strIpparaCfg.struStreamMode[iChannum].uGetStream.struChanInfo.byEnable == 1) {
                    log.info("IP通道" + channum + "在线");
                    byte byIPID = m_strIpparaCfg.struStreamMode[iChannum].uGetStream.struChanInfo.byIPID;
                    byte byIPIDHigh = m_strIpparaCfg.struStreamMode[iChannum].uGetStream.struChanInfo.byIPIDHigh;
                    int iDevID = (byIPIDHigh & 255) * 256 + (byIPID & 255);
                    int iDevInfoIndex = iDevID - 1;
                    byte[] sIpV4 = m_strIpparaCfg.struIPDevInfo[iDevInfoIndex].struIP.sIpV4;
                    String deviceIP = (new String(sIpV4)).trim();
                    if (deviceIP.equals(ipAddr)) {
                        return channum;
                    }
                } else {
                    log.info("IP通道" + channum + "不在线");
                }
            }
        }

        return null;
    }

    public static List<HikNvrChannelInfo> getIPChannelCount(Integer userID) {
        IntByReference ibrBytesReturned = new IntByReference(0);
        NET_DVR_IPPARACFG_V40 m_strIpparaCfg = new NET_DVR_IPPARACFG_V40();
        m_strIpparaCfg.write();
        Pointer lpIpParaConfig = m_strIpparaCfg.getPointer();
        hCNetSDK.NET_DVR_GetDVRConfig(userID, 1062, 0, lpIpParaConfig, m_strIpparaCfg.size(), ibrBytesReturned);
        m_strIpparaCfg.read();
        log.info("起始数字通道号：" + m_strIpparaCfg.dwStartDChan);
        List<HikNvrChannelInfo> list = new ArrayList();

        for(int iChannum = 0; iChannum < m_strIpparaCfg.dwDChanNum; ++iChannum) {
            m_strIpparaCfg.struStreamMode[iChannum].read();
            if (m_strIpparaCfg.struStreamMode[iChannum].byGetStreamType == 0) {
                m_strIpparaCfg.struStreamMode[iChannum].uGetStream.setType(NET_DVR_IPCHANINFO.class);
                m_strIpparaCfg.struStreamMode[iChannum].uGetStream.struChanInfo.read();
                if (m_strIpparaCfg.struStreamMode[iChannum].uGetStream.struChanInfo.byEnable == 1) {
                    log.info("IP通道" + iChannum + "在线");
                    byte byIPID = m_strIpparaCfg.struStreamMode[iChannum].uGetStream.struChanInfo.byIPID;
                    byte byIPIDHigh = m_strIpparaCfg.struStreamMode[iChannum].uGetStream.struChanInfo.byIPIDHigh;
                    int iDevID = (byIPIDHigh & 255) * 256 + (byIPID & 255);
                    int iDevInfoIndex = iDevID - 1;
                    byte[] sIpV4 = m_strIpparaCfg.struIPDevInfo[iDevInfoIndex].struIP.sIpV4;
                    String deviceIP = (new String(sIpV4)).trim();
                    HikNvrChannelInfo channelInfo = new HikNvrChannelInfo();
                    channelInfo.setChannel(iChannum + 1);
                    channelInfo.setIpAddr(deviceIP);
                    list.add(channelInfo);
                } else {
                    log.info("IP通道" + iChannum + "不在线");
                }
            }
        }

        return list;
    }

    public static int getVideoEncodingType(Integer userId) {
        NET_DVR_COMPRESSIONCFG_V30 compressionCfg = new NET_DVR_COMPRESSIONCFG_V30();
        compressionCfg.write();
        IntByReference bytesReturned = new IntByReference(0);
        boolean result = hCNetSDK.NET_DVR_GetDVRConfig(userId, 1040, 1, compressionCfg.getPointer(), compressionCfg.size(), bytesReturned);
        if (result) {
            compressionCfg.read();
            NET_DVR_COMPRESSION_INFO_V30 mainStreamCompressionInfo = compressionCfg.struNormHighRecordPara;
            byte encodingType = mainStreamCompressionInfo.byVideoEncType;
            switch(encodingType) {
                case 0:
                case 1:
                    return 264;
                case 10:
                    return 265;
                default:
                    return 0;
            }
        } else {
            log.info("获取视频编码类型失败，错误码: " + hCNetSDK.NET_DVR_GetLastError());
            return 0;
        }
    }

    public static void main(String[] args) {
        Integer userId = loginDevice("192.168.3.96", (short)8000, "admin", "ch210000");
        int videoEncodingType = getVideoEncodingType(userId);
        System.out.println(videoEncodingType);
    }

    static {
        hCNetSDK = (HCNetSDK)hikSDKHashMap.get("hCNetSDK");
        createSDKInstance();
    }
}

