package com.njcn.influx.event.type.jna;

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Structure;

import java.io.*;
import java.util.Arrays;
import java.util.List;

/**
 * JNA接口调用qvvr_dll.dll
 */
public interface QvvrDLL extends Library {

    /**
     * 加载DLL - 从resource目录或classpath
     */
    QvvrDLL INSTANCE = loadLibrary();
    
    /**
     * 支持jar打包的库加载方法 - 从jar内resources提取到临时目录后加载
     */
    static QvvrDLL loadLibrary() {
        String osName = System.getProperty("os.name").toLowerCase();
        String libFileName;
        String resourcePath;
        
        // 根据操作系统确定库文件名
        if (osName.contains("windows")) {
            libFileName = "qvvr_dll.dll";
            resourcePath = "/qvvr_dll.dll";
        } else if (osName.contains("linux")) {
            libFileName = "libqvvr_dll.so";
            resourcePath = "/libqvvr_dll.so";
        } else {
            throw new UnsupportedOperationException("不支持的操作系统: " + osName);
        }
        
        try {
            // 从jar中提取库文件到临时目录
            File tempLibFile = extractLibraryFromJar(resourcePath, libFileName);
            // 加载提取的库文件
            System.out.println("加载库文件: " + tempLibFile.getAbsolutePath());
            return Native.load(tempLibFile.getAbsolutePath(), QvvrDLL.class);
        } catch (Exception e) {
            throw new RuntimeException(
                "无法加载QVVR库文件。\n" +
                "请确保文件 " + libFileName + " 存在于 src/main/resources/ 目录下。\n" +
                "当前操作系统: " + osName,
                e
            );
        }
    }

    /**
     * 从jar中提取库文件到临时目录
     */
     static File extractLibraryFromJar(String resourcePath, String libFileName) throws IOException {
        // 获取资源输入流
        InputStream libStream = QvvrDLL.class.getResourceAsStream(resourcePath);
        if (libStream == null) {
            throw new FileNotFoundException("在jar中找不到库文件: " + resourcePath);
        }

        // 创建临时文件
        String tempDir = System.getProperty("java.io.tmpdir");
         File tempLibFile = new File(tempDir, libFileName);

        // File tempLibFile = new File(tempDir, "qvvr_" + System.currentTimeMillis() + "_" + libFileName);

        // 提取库文件到临时目录
        try (FileOutputStream out = new FileOutputStream(tempLibFile)) {
            byte[] buffer = new byte[8192];
            int bytesRead;
            while ((bytesRead = libStream.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
            }
        } finally {
            libStream.close();
        }

        // 设置为可执行
        tempLibFile.setExecutable(true);
        tempLibFile.setReadable(true);

        // JVM退出时删除临时文件
        tempLibFile.deleteOnExit();

        System.out.println("已提取库文件到: " + tempLibFile.getAbsolutePath());
        return tempLibFile;
    }

    /**
     * 直接调用C DLL的qvvr_fun函数
     * void __stdcall qvvr_fun(void *data)
     */
    void qvvr_fun(QvvrDataStruct data);

    void ping();

    /**
     * 对应C语言的qvvr_data_struct结构体
     */
    public static class QvvrDataStruct extends Structure {

        // 输入数据
        public float[] smp_va = new float[128 * 50 * 120];   // A相电压
        public float[] smp_vb = new float[128 * 50 * 120];   // B相电压
        public float[] smp_vc = new float[128 * 50 * 120];   // C相电压
        public int smp_rate;                                 // 采样频率
        public int smp_len;                                  // 数据长度

        // 输出结果
        public int evt_num;                                  // 事件数量
        public EventBuffer[] evt_buf = new EventBuffer[32];  // 事件缓冲区

        @Override
        protected List<String> getFieldOrder() {
            return Arrays.asList("smp_va", "smp_vb", "smp_vc", "smp_rate", "smp_len", "evt_num", "evt_buf");
        }

        public QvvrDataStruct() {
            super();
            // 初始化事件缓冲区
            for (int i = 0; i < 32; i++) {
                evt_buf[i] = new EventBuffer();
            }
        }
    }

    /**
     * 事件缓冲区结构
     */
    public static class EventBuffer extends Structure {
        public int[] qvvr_cata_cause = new int[256];
        public int[] qvvr_phasetype = new int[256];
        public int[] qvvr_cata_type = new int[256];

        public float hold_time_rms;
        public float hold_time_dq;

        public float POW_a;
        public float POW_b;
        public float POW_c;

        public float Voltagechange_Va;
        public float Voltagechange_Vb;
        public float Voltagechange_Vc;

        public int SEG_T_num;
        public int[] SEG_T0_idx = new int[256];
        public int[] SEG_T_idx = new int[256];

        public int SEG_RMS_T_num;
        public int[] SEG_RMS_T_idx = new int[256];

        public int u_min_num;
        public float[] ua_min = new float[256];
        public float[] ub_min = new float[256];
        public float[] uc_min = new float[256];
        public float[] u3_min = new float[256];
        public int[] order_min_idx = new int[256];

        public float[] angle_diff_ap = new float[256];
        public float[] angle_diff_bp = new float[256];
        public float[] angle_diff_cp = new float[256];
        public float[] angle_diff_an = new float[256];
        public float[] angle_diff_bn = new float[256];
        public float[] angle_diff_cn = new float[256];

        public float[] bph_max_value = new float[256];

        @Override
        protected List<String> getFieldOrder() {
            return Arrays.asList(
                "qvvr_cata_cause", "qvvr_phasetype", "qvvr_cata_type",
                "hold_time_rms", "hold_time_dq",
                "POW_a", "POW_b", "POW_c",
                "Voltagechange_Va", "Voltagechange_Vb", "Voltagechange_Vc",
                "SEG_T_num", "SEG_T0_idx", "SEG_T_idx",
                "SEG_RMS_T_num", "SEG_RMS_T_idx",
                "u_min_num", "ua_min", "ub_min", "uc_min", "u3_min", "order_min_idx",
                "angle_diff_ap", "angle_diff_bp", "angle_diff_cp",
                "angle_diff_an", "angle_diff_bn", "angle_diff_cn",
                "bph_max_value"
            );
        }
    }
}