package com.sunyard.chsm.sdf.adapter;

import com.sun.jna.Native;
import com.sun.jna.ptr.PointerByReference;
import com.sunyard.chsm.sdf.context.AlgId;
import com.sunyard.chsm.sdf.context.SunyardAlgId;
import com.sunyard.chsm.sdf.lib.SunyardSdfLibrary;

import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author liulu
 * @since 2024/11/4
 */
public class SunyardJnaSdfAdaptor extends JnaSdfAdaptor {

    private static final Map<String, SunyardSdfLibrary> SDF_LIB_MAP = new ConcurrentHashMap<>();


    private final String ip;
    private final Integer port;
    private final Integer connTimeout;
    private final Integer dealTimeout;

    public SunyardJnaSdfAdaptor(String ip) {
        this(ip, 8889, "sdf");
    }

    public SunyardJnaSdfAdaptor(String ip, int port) {
        this(ip, port, "sdf");
    }

    public SunyardJnaSdfAdaptor(String ip, int port, String libName) {
        this(ip, port, libName, 3000, 3000);
    }

    public SunyardJnaSdfAdaptor(String ip, int port, String libName, int connTimeout, int dealTimeout) {
        super(SDF_LIB_MAP.computeIfAbsent(libName, k -> Native.load(libName, SunyardSdfLibrary.class)));
        this.ip = ip;
        this.port = port;
        this.connTimeout = connTimeout;
        this.dealTimeout = dealTimeout;
    }

    @Override
    public String openDevice() {
        SunyardSdfLibrary sunyardSdfLibrary = (SunyardSdfLibrary) sdfLibrary;
        PointerByReference phDeviceHandle = new PointerByReference();
        sunyardSdfLibrary.SDF_OpenDevice(phDeviceHandle, safeStringBytes(ip), port, connTimeout, dealTimeout, 0);
        String key = UUID.randomUUID().toString();
        DEVICE_HANDLE_CONTEXT.put(key, phDeviceHandle.getValue());
        return key;
    }

    @Override
    protected int getAlgId(AlgId alg) {
        return SunyardAlgId.valueOf(alg.name()).getValue();
    }

    public static byte[] safeStringBytes(String str) {
        if (null == str || str.isEmpty()) {
            return new byte[]{0x30};
        }
        int len = str.getBytes().length;
        byte[] ret = new byte[len + 1];
        System.arraycopy(str.getBytes(), 0, ret, 0, len);
        return ret;
    }

}
