package com.cm.smartgate.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import netmanager.lib.PlatUtils;
import netmanager.lib.netmanager.NetLib;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * When you feel like quitting. Think about why you started
 * 当你想要放弃的时候，想想当初你为何开始
 *
 * @ClassName: AbstractSmartGateOperationService
 * @Description: 智能网闸操作服务
 * @Author: WangGeng
 * @Date: 2020/9/27 15:59
 * @Version: 1.0
 **/
public abstract class AbstractSmartGateOperationService {

    private static final Logger LOG = LoggerFactory.getLogger(AbstractSmartGateOperationService.class);

    /**
     * 运行
     *
     * @param ip
     * @param port
     * @param username
     * @param password
     * @return
     */
    public boolean run(String ip, int port, String username, String password, int mode) {
        NetLib instance = null;
        IntByReference error = null;
        NativeLong loginID = null;
        try {
            instance = (NetLib) Native.loadLibrary(PlatUtils.sdk_plat_getLoadLibrary(getConfigPath(), "netmanager"), NetLib.class);
            instance.Net_Init(null, null);
            loginID = instance.Net_LoginDevice(ip, port, username, password, null, error);
            LOG.debug("Username: {}, password: {}, ip: {}, port: {}", username, password, ip, port);
            LOG.debug("String login, login id:" + loginID);
            if (0 == loginID.longValue()) {
                LOG.error("Login error");
                return false;
            }
            JSONObject settingObj = getConfigSetting(mode);
            String tData = settingObj.toJSONString();
            int dwInBufferSize = tData.length();
            Pointer szInBuffer = new Memory(dwInBufferSize + 200);
            szInBuffer.setString(0, tData);
            int dwOutBufferSize = 128;
            Pointer szOutBuffer = new Memory(dwOutBufferSize);
            LOG.debug("Send setting: {}", szInBuffer.getString(0));
            instance.Net_TransJsonByRpc(loginID, szInBuffer, dwInBufferSize, szOutBuffer, dwOutBufferSize, null, 6000);
            LOG.debug("Return setting: {}", szOutBuffer.getString(0));
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            return false;
        } finally {
            if (loginID != null) {
                instance.Net_LogoutDevice(loginID);
            }
            if (instance != null) {
                instance.Net_Exit();
            }
        }
        return true;
    }

    protected abstract JSONObject getConfigSetting(int mode);

    protected abstract String getConfigPath();

    /**
     * 获取配置json对象
     *
     * @param paramsName
     * @param contentObj
     * @return
     */
    protected JSONObject initConfigSetting(String paramsName, JSONObject contentObj) {
        JSONObject settingObj = new JSONObject();
        settingObj.put("id", 1);
        settingObj.put("method", "configCentre.setConfig");
        JSONObject paramsObj = new JSONObject();
        paramsObj.put("name", paramsName);
        JSONArray contentArray = new JSONArray();
        contentArray.add(contentObj);
        paramsObj.put("content", contentArray);
        settingObj.put("params", paramsObj);
        return settingObj;
    }

    /**
     * 初始化认证类型
     *
     * @param paramsName
     * @param contentObj
     * @return
     */
    protected JSONObject initTrustSetting(String paramsName, JSONObject contentObj) {
        JSONObject settingObj = new JSONObject();
        settingObj.put("id", 1);
        settingObj.put("method", "configCentre.setConfig");
        JSONObject paramsObj = new JSONObject();
        paramsObj.put("name", paramsName);
        paramsObj.put("content", contentObj);
        settingObj.put("params", paramsObj);
        return settingObj;
    }

    /**
     * 开门
     *
     * @return
     */
    protected JSONObject getOpenDoor() {
        JSONObject settingObj = new JSONObject();
        settingObj.put("id", 2);
        settingObj.put("method", "devDoor.openOnce");
        JSONObject params = new JSONObject();
        params.put("channel", 0);
        settingObj.put("params", params);
        return settingObj;
    }

}
