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

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.hikvision.artemis.sdk.ArtemisHttpUtil;
import com.hikvision.artemis.sdk.config.ArtemisConfig;
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.HikApiRest;
import com.mortals.xhx.module.hik.door.model.req.door.DoorEventReq;
import com.mortals.xhx.module.hik.door.model.req.door.HikDoorEventReq;
import com.mortals.xhx.module.hik.door.model.rsp.door.DoorEventDataInfo;
import com.mortals.xhx.module.hik.door.model.rsp.door.info.EventInfo;
import com.mortals.xhx.module.hik.door.service.IHikDoorService;
import com.sun.jna.Pointer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.*;

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


    @Override
    public Rest<DoorEventDataInfo> getDoorEvents(DoorEventReq doorEventReq) {
        ArtemisConfig config = getArtemisConfig();
        String getCamsApi = ARTEMIS_PATH + "/api/acs/v2/door/events";
        Map<String, String> path = new HashMap<>(2);
        path.put(protocol, getCamsApi);
        try {
            log.info("door events req=>{}", JSON.toJSONString(doorEventReq));
            String respJson = ArtemisHttpUtil.doPostStringArtemis(config, path, JSON.toJSONString(doorEventReq), null, null, "application/json");
            //log.info("door events error resp=>{}", respJson);
            HikApiRest<DoorEventDataInfo> rest = JSON.parseObject(respJson, new TypeReference<HikApiRest<DoorEventDataInfo>>() {
            });
            log.info("door events  resp=>{}", rest.getCode());
            if ("0".equals(rest.getCode())) {
                return Rest.ok(rest.getData());
            } else {
                return Rest.fail(rest.getMsg());
            }
        } catch (Exception e) {
            log.error("获取门禁事件异常", e);
            return Rest.fail(e.getMessage());
        }
    }

    @Override
    public Rest<List<EventInfo>> searchDoorEventsList(HikDoorEventReq hikDoorEventReq, DoorEntity doorEntity) {
        HCNetSDK hCNetSDK = createSDKInstance();
        //initLoadSdk(hCNetSDK);
        int userID = login(hCNetSDK, doorEntity);
        List<EventInfo> eventInfoList = new ArrayList<>();

        int i = 0; //事件条数
        HCNetSDK.NET_DVR_ACS_EVENT_COND struAcsEventCond = new HCNetSDK.NET_DVR_ACS_EVENT_COND();
        struAcsEventCond.read();
        struAcsEventCond.dwSize = struAcsEventCond.size();
        //查询全部主次类型的报警
        struAcsEventCond.dwMajor = 5; // 主次事件类型设为0，代表查询所有事件
        struAcsEventCond.dwMinor = 0; //

        Date startTime = hikDoorEventReq.getStartTime();
        Date endTime = hikDoorEventReq.getEndTime();

        //开始时间
        struAcsEventCond.struStartTime.dwYear = DateUtil.year(startTime);
        struAcsEventCond.struStartTime.dwMonth = DateUtil.month(startTime) + 1;
        struAcsEventCond.struStartTime.dwDay = DateUtil.dayOfMonth(startTime);
        struAcsEventCond.struStartTime.dwHour = DateUtil.hour(startTime, true);
        struAcsEventCond.struStartTime.dwMinute = DateUtil.minute(startTime);
        struAcsEventCond.struStartTime.dwSecond = DateUtil.second(startTime);
        //结束时间
        struAcsEventCond.struEndTime.dwYear = DateUtil.year(endTime);
        struAcsEventCond.struEndTime.dwMonth = DateUtil.month(endTime) + 1;
        struAcsEventCond.struEndTime.dwDay = DateUtil.dayOfMonth(endTime);
        struAcsEventCond.struEndTime.dwHour = DateUtil.hour(endTime, true);
        struAcsEventCond.struEndTime.dwMinute = DateUtil.minute(endTime);
        struAcsEventCond.struEndTime.dwSecond = DateUtil.second(endTime);
        struAcsEventCond.wInductiveEventType = 1;
        struAcsEventCond.byPicEnable = 0; //是否带图片，0-不带图片，1-带图片
        struAcsEventCond.write();
        Pointer ptrStruEventCond = struAcsEventCond.getPointer();

        try {
            int m_lSearchEventHandle = hCNetSDK.NET_DVR_StartRemoteConfig(userID, HCNetSDK.NET_DVR_GET_ACS_EVENT, ptrStruEventCond, struAcsEventCond.size(), null, null);
            if (m_lSearchEventHandle <= -1) {
                log.info("NET_DVR_StartRemoteConfig调用失败，错误码:{} ,考勤设备:{}" , hCNetSDK.NET_DVR_GetLastError(),doorEntity.getDeviceName());
                throw new AppException("NET_DVR_StartRemoteConfig调用失败，错误码:" + hCNetSDK.NET_DVR_GetLastError());
            }
            HCNetSDK.NET_DVR_ACS_EVENT_CFG struAcsEventCfg = new HCNetSDK.NET_DVR_ACS_EVENT_CFG();
            struAcsEventCfg.read();
            struAcsEventCfg.dwSize = struAcsEventCfg.size();
            struAcsEventCfg.write();
            Pointer ptrStruEventCfg = struAcsEventCfg.getPointer();
            int recount=0;
            while (true) {
                int dwEventSearch = hCNetSDK.NET_DVR_GetNextRemoteConfig(m_lSearchEventHandle, ptrStruEventCfg, struAcsEventCfg.size());
                if (dwEventSearch <= -1) {
                    log.info("NET_DVR_GetNextRemoteConfig接口调用失败，错误码：" + hCNetSDK.NET_DVR_GetLastError());
                    throw new AppException("NET_DVR_GetNextRemoteConfig接口调用失败，错误码：" + hCNetSDK.NET_DVR_GetLastError());
                }
                if (dwEventSearch == HCNetSDK.NET_SDK_GET_NEXT_STATUS_NEED_WAIT) {
                    log.info("配置等待....");
                    recount++;
                    if(recount>5) break;
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {

                    }
                } else if (dwEventSearch == HCNetSDK.NET_SDK_NEXT_STATUS__FINISH) {
                    log.info("获取事件完成");
                    break;
                } else if (dwEventSearch == HCNetSDK.NET_SDK_GET_NEXT_STATUS_FAILED) {
                    log.info("获取事件出现异常");
                    break;
                } else if (dwEventSearch == HCNetSDK.NET_SDK_GET_NEXT_STATUS_SUCCESS) {
                    struAcsEventCfg.read();
                    EventInfo eventInfo = JSON.parseObject(JSON.toJSONString(struAcsEventCfg), EventInfo.class);
                    //获取的事件信息通过struAcsEventCfg结构体进行解析，
                    log.info(i + "获取事件成功, 报警主类型：" + Integer.toHexString(struAcsEventCfg.dwMajor) + "报警次类型：" + Integer.toHexString(struAcsEventCfg.dwMinor) + "  卡号：" + new String(struAcsEventCfg.struAcsEventInfo.byCardNo).trim());

                    /**
                     * 工号有两个字段，dwEmployeeNo表示工号，当值为0时，表示无效，解析byEmployeeNo参数
                     */
                    log.info("工号1：" + struAcsEventCfg.struAcsEventInfo.dwEmployeeNo);
                    log.info("工号2：" + new String(struAcsEventCfg.struAcsEventInfo.byEmployeeNo));
                    log.info("考勤状态值:" + struAcsEventCfg.struAcsEventInfo.byStatusValue);
                    log.info("时间:" + struAcsEventCfg.struTime);
                    eventInfoList.add(eventInfo);
                    i++;
                }
            }
            i = 0;
            if (!hCNetSDK.NET_DVR_StopRemoteConfig(m_lSearchEventHandle)) {
                log.info("NET_DVR_StopRemoteConfig接口调用失败，错误码：" + hCNetSDK.NET_DVR_GetLastError());
            } else {
                log.info("NET_DVR_StopRemoteConfig接口成功");
            }

        } catch (Exception e) {
            log.error("获取事件异常", e.getMessage());
        }finally {
            logout(hCNetSDK,userID);
        }
        return Rest.ok(eventInfoList);


    }


}
