package com.mortals.xhx.module.hik.staff.service.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.mortals.framework.common.Rest;
import com.mortals.framework.exception.AppException;
import com.mortals.xhx.hikdoor.NetSDKDemo.HCNetSDK;
import com.mortals.xhx.module.door.model.DoorEntity;
import com.mortals.xhx.module.hik.AbstractHikService;
import com.mortals.xhx.module.hik.staff.model.req.staff.StaffReq;
import com.mortals.xhx.module.hik.staff.model.rsp.staff.search.UserSearchInfo;
import com.mortals.xhx.module.hik.staff.service.IHikStaffService;
import com.sun.jna.ptr.IntByReference;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONObject;
import org.springframework.stereotype.Service;

import java.util.Date;

/**
 * 海康人员接口类
 *
 * @author: zxfei
 * @date: 2023/4/12 17:51
 */
@Service("hikStaffService")
@Slf4j
public class HikStaffServiceImpl extends AbstractHikService implements IHikStaffService {

    //查询所有人员
    @Override
    public Rest<UserSearchInfo> getPersonList(StaffReq personReq, DoorEntity doorEntity) {
        //todo 新的链接设备
        HCNetSDK hCNetSDK = createSDKInstance();
       // initLoadSdk(hCNetSDK);
        int userID = login(hCNetSDK, doorEntity);

        HCNetSDK.BYTE_ARRAY ptrByteArray = new HCNetSDK.BYTE_ARRAY(1024);    //数组
        String strInBuffer = "POST /ISAPI/AccessControl/UserInfo/Search?format=json";
        System.arraycopy(strInBuffer.getBytes(), 0, ptrByteArray.byValue, 0, strInBuffer.length());//字符串拷贝到数组中
        ptrByteArray.write();
        String resp = "";
        try {
            int lHandler = hCNetSDK.NET_DVR_StartRemoteConfig(userID, HCNetSDK.NET_DVR_JSON_CONFIG, ptrByteArray.getPointer(), strInBuffer.length(), null, null);
            if (lHandler < 0) {
                log.info("SearchUserInfo NET_DVR_StartRemoteConfig 失败,错误码为==>{}", hCNetSDK.NET_DVR_GetLastError());
                throw new AppException(String.format("SearchUserInfo NET_DVR_StartRemoteConfig 失败,错误码为==>%s", hCNetSDK.NET_DVR_GetLastError()));
            } else {
                JSONObject jsonObject = new JSONObject();
                JSONObject jsonSearchCond = new JSONObject();

                jsonSearchCond.put("searchID", DateUtil.format(new Date(), "yyyyMMdd"));
                jsonSearchCond.put("searchResultPosition", personReq.getPageNo()*personReq.getPageSize());
                jsonSearchCond.put("maxResults", personReq.getPageSize());
                jsonObject.put("UserInfoSearchCond", jsonSearchCond);

                String strInbuff = jsonObject.toString();
                log.info("UserInfo/Search 请求json报文==>{}", strInbuff);
                //把string传递到Byte数组中，后续用.getPointer()方法传入指针地址中。
                HCNetSDK.BYTE_ARRAY ptrInbuff = new HCNetSDK.BYTE_ARRAY(strInbuff.length());
                System.arraycopy(strInbuff.getBytes(), 0, ptrInbuff.byValue, 0, strInbuff.length());
                ptrInbuff.write();
                //定义接收结果的结构体
                HCNetSDK.BYTE_ARRAY ptrOutuff = new HCNetSDK.BYTE_ARRAY(1024 * 1024);
                IntByReference pInt = new IntByReference(0);
                while (true) {
                    int dwState = hCNetSDK.NET_DVR_SendWithRecvRemoteConfig(lHandler, ptrInbuff.getPointer(), strInbuff.length(), ptrOutuff.getPointer(), 1024 * 1024, pInt);
                    log.info("dwState<=={}", dwState);
                    if (dwState == -1) {
                        log.info("NET_DVR_SendWithRecvRemoteConfig接口调用失败，错误码：{}", hCNetSDK.NET_DVR_GetLastError());
                        throw new AppException(String.format("NET_DVR_SendWithRecvRemoteConfig接口调用失败，错误码：%s", hCNetSDK.NET_DVR_GetLastError()));
                        //   break;
                    } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_NEED_WAIT) {
                        log.info("配置等待");
                        try {
                            Thread.sleep(10);
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                        continue;
                    } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_FAILED) {
                        log.info("查询人员失败");
                        throw new AppException(String.format("查询人员失败，错误码：%s", HCNetSDK.NET_SDK_CONFIG_STATUS_FAILED));
                        // break;
                    } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_EXCEPTION) {
                        log.info("查询人员异常");
                        throw new AppException(String.format("查询人员异常，错误码：%s", HCNetSDK.NET_SDK_CONFIG_STATUS_EXCEPTION));
                        // break;
                    } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_SUCCESS) {
                        ptrOutuff.read();
                        resp = new String(ptrOutuff.byValue).trim();
                        log.info("查询人员成功, json==>{}", resp);
                        break;
                    } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_FINISH) {
                        log.info("获取人员完成");
                        break;
                    }
                }
                if (!hCNetSDK.NET_DVR_StopRemoteConfig(lHandler)) {
                    log.info("NET_DVR_StopRemoteConfig接口调用失败，错误码==>{}", hCNetSDK.NET_DVR_GetLastError());
                    throw new AppException(String.format("NET_DVR_StopRemoteConfig接口调用失败，错误码==>{}", hCNetSDK.NET_DVR_GetLastError()));
                } else {
                    log.info("NET_DVR_StopRemoteConfig接口成功");
                }
            }
            UserSearchInfo userSearchInfo = JSON.parseObject(resp, new TypeReference<UserSearchInfo>() {
            });
            logout(hCNetSDK,userID);
            return Rest.ok(userSearchInfo);
        } catch (Exception e) {
            log.error("获取人员异常", e);
            return Rest.fail(e.getMessage());
        }
    }

    @Override
    public Rest<UserSearchInfo> getPersonCount(StaffReq personReq, DoorEntity doorEntity) {
        HCNetSDK hCNetSDK = createSDKInstance();
        //initLoadSdk(hCNetSDK);
        int userID = login(hCNetSDK, doorEntity);

        HCNetSDK.BYTE_ARRAY ptrByteArray = new HCNetSDK.BYTE_ARRAY(1024);    //数组
        String strInBuffer = "POST /ISAPI/AccessControl/UserInfo/Search?format=json";
        System.arraycopy(strInBuffer.getBytes(), 0, ptrByteArray.byValue, 0, strInBuffer.length());//字符串拷贝到数组中
        ptrByteArray.write();
        String resp = "";
        try {
            int lHandler = hCNetSDK.NET_DVR_StartRemoteConfig(userID, HCNetSDK.NET_DVR_JSON_CONFIG, ptrByteArray.getPointer(), strInBuffer.length(), null, null);
            if (lHandler < 0) {
                log.info("SearchUserInfo NET_DVR_StartRemoteConfig 失败,错误码为==>{}", hCNetSDK.NET_DVR_GetLastError());
                throw new AppException(String.format("SearchUserInfo NET_DVR_StartRemoteConfig 失败,错误码为==>%s", hCNetSDK.NET_DVR_GetLastError()));
            } else {
                //组装查询的JSON报文，这边查询的是所有的人员
                JSONObject jsonObject = new JSONObject();
                JSONObject jsonSearchCond = new JSONObject();

                jsonSearchCond.put("searchID", DateUtil.format(new Date(), "yyyyMMdd"));
                jsonSearchCond.put("searchResultPosition", 0);
                jsonSearchCond.put("maxResults", 1);
                jsonObject.put("UserInfoSearchCond", jsonSearchCond);

                String strInbuff = jsonObject.toString();
                log.info("UserInfo/Search 请求json报文==>{}", strInbuff);
                //把string传递到Byte数组中，后续用.getPointer()方法传入指针地址中。
                HCNetSDK.BYTE_ARRAY ptrInbuff = new HCNetSDK.BYTE_ARRAY(strInbuff.length());
                System.arraycopy(strInbuff.getBytes(), 0, ptrInbuff.byValue, 0, strInbuff.length());
                ptrInbuff.write();
                //定义接收结果的结构体
                HCNetSDK.BYTE_ARRAY ptrOutuff = new HCNetSDK.BYTE_ARRAY(1 * 1024);
                IntByReference pInt = new IntByReference(0);
                while (true) {
                    int dwState = hCNetSDK.NET_DVR_SendWithRecvRemoteConfig(lHandler, ptrInbuff.getPointer(), strInbuff.length(), ptrOutuff.getPointer(), 1 * 1024, pInt);
                    log.info("dwState<=={}", dwState);
                    if (dwState == -1) {
                        log.info("NET_DVR_SendWithRecvRemoteConfig接口调用失败，错误码：{}", hCNetSDK.NET_DVR_GetLastError());
                        throw new AppException(String.format("NET_DVR_SendWithRecvRemoteConfig接口调用失败，错误码：%s", hCNetSDK.NET_DVR_GetLastError()));
                        //   break;
                    } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_NEED_WAIT) {
                        log.info("配置等待");
                        try {
                            Thread.sleep(10);
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                        continue;
                    } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_FAILED) {
                        log.info("查询人员失败");
                        throw new AppException(String.format("查询人员失败，错误码：%s", HCNetSDK.NET_SDK_CONFIG_STATUS_FAILED));
                        // break;
                    } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_EXCEPTION) {
                        log.info("查询人员异常");
                        throw new AppException(String.format("查询人员异常，错误码：%s", HCNetSDK.NET_SDK_CONFIG_STATUS_EXCEPTION));
                        // break;
                    } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_SUCCESS) {
                        ptrOutuff.read();
                        resp = new String(ptrOutuff.byValue).trim();
                        log.info("查询人员成功, json==>{}", resp);
                        break;
                    } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_FINISH) {
                        log.info("获取人员完成");
                        break;
                    }
                }
                if (!hCNetSDK.NET_DVR_StopRemoteConfig(lHandler)) {
                    log.info("NET_DVR_StopRemoteConfig接口调用失败，错误码==>{}", hCNetSDK.NET_DVR_GetLastError());
                    throw new AppException(String.format("NET_DVR_StopRemoteConfig接口调用失败，错误码==>{}", hCNetSDK.NET_DVR_GetLastError()));
                } else {
                    log.info("NET_DVR_StopRemoteConfig接口成功");
                }
            }
            UserSearchInfo userSearchInfo = JSON.parseObject(resp, new TypeReference<UserSearchInfo>() {
            });

            logout(hCNetSDK,userID);
            return Rest.ok(userSearchInfo);
        } catch (Exception e) {
            log.error("获取人员异常", e);
            return Rest.fail(e.getMessage());
        }
    }

    @Override
    public Rest<UserSearchInfo> getPersonPicByDevices(StaffReq personReq, DoorEntity doorEntity) {
        return null;
    }

    @Override
    public Rest<UserSearchInfo> downPersonPicToDevice(StaffReq personReq, DoorEntity doorEntity) {
        return null;
    }

}
