package com.iailab.module.data.video.dahua;

import com.iailab.module.data.video.config.VideoConfiguration;
import com.iailab.module.data.video.dahua.frame.DHCapturePictureFrame;
import com.iailab.netsdk.common.Res;
import com.iailab.netsdk.demo.module.LoginModule;
import com.iailab.netsdk.demo.module.RealPlayModule;
import com.iailab.netsdk.lib.NetSDKLib;
import com.iailab.netsdk.lib.ToolKits;
import com.sun.jna.CallbackThreadInitializer;
import com.sun.jna.Native;
import com.sun.jna.ptr.IntByReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.awt.*;
import java.io.File;
import java.util.*;

/**
 * @author PanZhibao
 * @Description
 * @createTime 2024年04月08日
 */
public class DHCapturePictureClient {
    private Logger logger = LoggerFactory.getLogger(getClass());

    // 登陆句柄
    public static NetSDKLib netsdk = NetSDKLib.NETSDK_INSTANCE;

    // 设备信息
    public static NetSDKLib.NET_DEVICEINFO_Ex m_stDeviceInfo = new NetSDKLib.NET_DEVICEINFO_Ex();

    private static boolean bInit = false;

    private static boolean bLogopen = false;

    private boolean bLogin = false;

    private boolean bRealPlay = false;

    private Panel realPlayWindow = new Panel();

    private String ip;

    private Vector<String> chnlist = new Vector<String>();

    private DisConnect disConnect = new DisConnect();

    private HaveReConnect haveReConnect = new HaveReConnect();

    private DHCaptureReceiveCB m_CaptureReceiveCB = new DHCaptureReceiveCB();

    public static boolean isInit () {
        return bInit;
    }

    public boolean isLogin () {
        return bLogin;
    }

    public String getIp () {
        return ip;
    }

    public Vector<String> getChnList() {
       return  chnlist;
    }

    // 登陆句柄
    public NetSDKLib.LLong m_hLoginHandle = new NetSDKLib.LLong(0);

    // realplay handle
    public NetSDKLib.LLong m_hPlayHandle = new NetSDKLib.LLong(0);

    private DHCapturePictureFrame cpf;

    DHCapturePictureClient() {
        cpf = new DHCapturePictureFrame(realPlayWindow);
        cpf.setVisible(true);
    }

    /**
     * 初始化SDK
     *
     * @return
     */
    public boolean initSDK() {

        bInit = netsdk.CLIENT_Init(disConnect, null);
        if(!bInit) {
            System.out.println("Initialize SDK failed");
            return false;
        }

        //打开日志,可选
        NetSDKLib.LOG_SET_PRINT_INFO setLog = new NetSDKLib.LOG_SET_PRINT_INFO();
        File path = new File("./sdklog/");
        if (!path.exists()) {
            path.mkdir();
        }
        String logPath = path.getAbsoluteFile().getParent() + "\\sdklog\\" + ToolKits.getDate() + ".log";
        setLog.nPrintStrategy = 0;
        setLog.bSetFilePath = 1;
        System.arraycopy(logPath.getBytes(), 0, setLog.szLogFilePath, 0, logPath.getBytes().length);
        System.out.println(logPath);
        setLog.bSetPrintStrategy = 1;
        bLogopen = netsdk.CLIENT_LogOpen(setLog);
        if(!bLogopen ) {
            System.err.println("Failed to open NetSDK log");
        }

        // 设置断线重连回调接口,设置过断线重连成功回调函数后,当设备出现断线情况,SDK内部会自动进行重连操作
        // 此操作为可选操作,但建议用户进行设置
        netsdk.CLIENT_SetAutoReconnect(haveReConnect, null);

        //设置登录超时时间和尝试次数,可选
        int waitTime = 5000; //登录请求响应超时时间设置为5S
        int tryTimes = 1;    //登录时尝试建立链接1次
        netsdk.CLIENT_SetConnectTime(waitTime, tryTimes);


        // 设置更多网络参数,NET_PARAM的nWaittime,nConnectTryNum成员与CLIENT_SetConnectTime
        // 接口设置的登录设备超时时间和尝试次数意义相同,可选
        NetSDKLib.NET_PARAM netParam = new NetSDKLib.NET_PARAM();
        netParam.nConnectTime = 10000;      // 登录时尝试建立链接的超时时间
        netParam.nGetConnInfoTime = 3000;   // 设置子连接的超时时间
        netParam.nGetDevInfoTime = 3000;//获取设备信息超时时间,为0默认1000ms
        netsdk.CLIENT_SetNetworkParam(netParam);
        if (!bInit) {
            logger.info("Initialize SDK Failed");
        } else {
            logger.info("Initialize SDK Success");
        }
        return bInit;
    }

    /**
     * \if ENGLISH_LANG
     * CleanUp
     * \else
     * 清除环境
     * \endif
     */
    public static void cleanup() {
        if(bLogopen) {
            netsdk.CLIENT_LogClose();
        }

        if(bInit) {
            netsdk.CLIENT_Cleanup();
        }
    }

    /**
     * 登录设备
     *
     * @param ip
     * @param port
     * @param username
     * @param password
     */
    public boolean login(String ip, int port, String username, String password) {
        this.ip = ip;
        if (!bInit) {
            return false;
        }
        Native.setCallbackThreadInitializer(m_CaptureReceiveCB,
                new CallbackThreadInitializer(false, false, "snapPicture callback thread"));

        //IntByReference nError = new IntByReference(0);
        //入参
        NetSDKLib.NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY pstInParam=new NetSDKLib.NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY();
        pstInParam.nPort=port;
        pstInParam.szIP=ip.getBytes();
        pstInParam.szPassword=password.getBytes();
        pstInParam.szUserName=username.getBytes();
        //出参
        NetSDKLib.NET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY pstOutParam=new NetSDKLib.NET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY();
        pstOutParam.stuDeviceInfo=m_stDeviceInfo;
        //m_hLoginHandle = netsdk.CLIENT_LoginEx2(m_strIp, m_nPort, m_strUser, m_strPassword, 0, null, m_stDeviceInfo, nError);
        m_hLoginHandle=netsdk.CLIENT_LoginWithHighLevelSecurity(pstInParam, pstOutParam);
        boolean ret = m_hLoginHandle.longValue() == 0? false:true;

        if (ret) {
            bLogin = true;
            for (int i = 1; i < LoginModule.m_stDeviceInfo.byChanNum + 1; i++) {
                chnlist.add(Res.string().getChannel() + " " + i);
            }
            NetSDKLib.NETSDK_INSTANCE.CLIENT_SetSnapRevCallBack(m_CaptureReceiveCB, null);
        } else {
            bLogin = false;
        };
        return bLogin;
    }

    /**
     * 登出设备
     */
    public void logout() {
        if(m_hLoginHandle.longValue() == 0) {
            return;
        }
        RealPlayModule.stopRealPlay(m_hPlayHandle);
        boolean bRet = netsdk.CLIENT_Logout(m_hLoginHandle);
        if(bRet) {
            m_hLoginHandle.setValue(0);
        }
        for (int i = 0; i < LoginModule.m_stDeviceInfo.byChanNum; i++) {
            chnlist.clear();
        }
        bInit = false;
    }

    /**
     * 远程抓图
     *
     * @param channel
     * @param serial
     * @return
     */
    public boolean remoteCapturePicture(int channel, String serial) {
        if (!bLogin) {
            logger.info("not login!");
            return false;
        }
        // send caputre picture command to device
        NetSDKLib.SNAP_PARAMS stuSnapParams = new NetSDKLib.SNAP_PARAMS();
        stuSnapParams.Channel = channel;  			// channel
        stuSnapParams.mode = 0;    			        // capture picture mode
        stuSnapParams.Quality = 3;				    // picture quality
        stuSnapParams.InterSnap = 0; 	            // timer capture picture time interval
        stuSnapParams.CmdSerial = Integer.parseInt(serial);  	        // request serial
        IntByReference reserved = new IntByReference(0);
        return NetSDKLib.NETSDK_INSTANCE.CLIENT_SnapPictureEx(this.m_hLoginHandle, stuSnapParams, reserved);
    }

    /**
     * 开始预览
     *
     * @param channel
     * @param stream
     * @param realPlayWindow
     * @return
     */
    public void startRealPlay(int channel, int stream, Panel realPlayWindow) {
        this.m_hPlayHandle = netsdk.CLIENT_RealPlayEx(this.m_hLoginHandle, channel, Native.getComponentPointer(realPlayWindow), stream);

        if(m_hPlayHandle.longValue() == 0) {
            System.err.println("开始实时预览失败,错误码" + ToolKits.getErrorCodePrint());
        } else {
            System.out.println("Success to start realplay");
        }
        bRealPlay = true;
    }

    /**
     * 停止预览
     */
    public void stopRealPlay() {
        if(m_hPlayHandle.longValue() == 0) {
            return;
        }

        boolean bRet = netsdk.CLIENT_StopRealPlayEx(m_hPlayHandle);
        if(bRet) {
            m_hPlayHandle.setValue(0);
        }

        realPlayWindow.repaint();
        bRealPlay = false;
    }

    /**
     * 本地抓图
     *
     * @param channel
     * @param cmdSerial
     * @return
     */
    public synchronized boolean localCapturePicture(int channel, String cmdSerial) {
        System.out.println("localCapturePicture:");
        try {
            this.startRealPlay(channel, 0, realPlayWindow);
            if(!bRealPlay) {
                return false;
            }
            Thread.sleep(2000);
            Calendar calendar = Calendar.getInstance();
            String strFileName = DHSavePath.getSavePath().getSaveCapturePath(cmdSerial, calendar.getTime());
            if (!netsdk.CLIENT_CapturePictureEx(this.m_hPlayHandle, strFileName, NetSDKLib.NET_CAPTURE_FORMATS.NET_CAPTURE_JPEG)) {
                System.err.printf("CLIENT_CapturePicture Failed!" + ToolKits.getErrorCodePrint());
                return false;
            } else {
                System.out.println("CLIENT_CapturePicture success");
                // 处理图片
                Map<String, String> params = new HashMap<>();
                params.put("strFileName", strFileName);
                params.put("cmdSerial", cmdSerial);
                params.put("brand", "DH");
                VideoConfiguration.staticCameraService.dealCapture(params);
            }
            return true;
        } catch (Exception ex) {
            ex.printStackTrace();
            return false;
        } finally {
            this.stopRealPlay();
        }
    }
}