import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import static lib.mtn_lib20.*;
import static lib.mtn_lib20_com.*;
import static lib.mtn_lib20_ext.*;
import static lib.mtn_lib20_oem.*;
import static lib.mtn_lib20_err.*;
import com.sun.jna.*;
import com.sun.jna.ptr.*;

public class Main {
    static {
        String libPath = System.getProperty("user.dir") + "\\lib";
        System.setProperty("java.library.path", libPath);
        System.load(libPath + "\\msvcr100.dll");
        System.load(libPath + "\\msvcp100.dll");
        System.load(libPath + "\\nmc_lib20.dll");
    }

    /**
     * 检查函数调用结果，处理错误
     */
    public static void checkError(short result, String operation) {
        if (result != RTN_CMD_SUCCESS) {
            System.err.printf("操作 %s 时发生错误 错误代码: %d%n", operation, result);
        }
    }

    public static void main(String[] args) {
        short rtn = 0;// 指令返回值
        short devNum = 0;// 设备序号，从0开始
        short axisNum = 0;// 轴号，从0开始

        // 句柄
        HAND devHandle = new HAND();// 设备句柄
        HAND axisHandle = new HAND();// 轴句柄
        HAND crdHandle = new HAND();// 坐标系句柄
        PHAND pDevHandle = new PHAND();//设备句柄指针
        PHAND pAxisHandle = new PHAND();//轴句柄指针
        PHAND pCrdHandle = new PHAND();// 坐标系句柄指针


        // 1. 打开设备
        rtn = NMC_DevOpen(devNum, pDevHandle);
        checkError(rtn, "NMC_DevOpen");
        devHandle = pDevHandle.getHandle();

        // 2. 打开轴
        rtn = NMC_MtOpen(devHandle, axisNum, pAxisHandle);
        checkError(rtn, "NMC_MtOpen");
        axisHandle = pAxisHandle.getHandle();

        // 3. 轴使能
        rtn = NMC_MtSetSvOn(axisHandle);
        checkError(rtn, "NMC_MtSetSvOn");

        /**
         * 正式测试部分
         */

        short chn = 0; // 通道号

        // a. 设置线性位置比较参数
        short dimens = 2;             // 表示二维（合成）位置比较
        short axisMask = 0x03;        // 轴掩码0x3 (第一个轴和第二轴)
        short src = 1;                // 位置源为规划位置
        short cmpMode = 0;            // 按输出数组位置比较
        double gateTime = 0.0009;     // 输出的脉冲宽度 (秒)

        // 在设置任何参数前，先关闭线性位置比较，避免“激活中”的错误
        System.out.println("=== 确保功能已关闭 ===");
        rtn = NMC_LinearCompOnOff(devHandle, (short) 0, chn); // 0: 关闭
        checkError(rtn, "NMC_LinearCompOnOff (Ensure Off)");
        if (rtn == RTN_CMD_SUCCESS) {
            System.out.println("✅ 已确保线性位置比较功能处于关闭状态");

            System.out.println("=== 设置线性位置比较参数 ===");
            System.out.printf("  维度: %d, 轴掩码: 0x%X, 位置源: %d%n", dimens, axisMask, src);
            System.out.printf("  比较模式: %d, 脉冲宽度: %.6f秒%n", cmpMode, gateTime);

            rtn = NMC_LinearCompSetParam(devHandle, dimens, axisMask, src, cmpMode, gateTime, chn);
            checkError(rtn, "NMC_LinearCompSetParam");
            if (rtn == RTN_CMD_SUCCESS) {
                System.out.println("✅ NMC_LinearCompSetParam 执行成功");
            }

            // b. 设置位置比较数据
            int dataCount = 100;
            // ✅ 位置数组
            NativeLong[] cmpPos = new NativeLong[dataCount];
            for (int i = 0; i < dataCount; i++) {
                cmpPos[i] = new NativeLong(i * 1000L); // 间隔位置为1000个脉冲
            }

            // ✅ 起始位置数组，两个轴的起始位置
            NativeLong[] startPos = new NativeLong[]{
                    new NativeLong(0),
                    new NativeLong(0)
            };

            System.out.println("\n=== 设置位置比较数据 ===");
            System.out.printf("  数据点数: %d%n", dataCount);
            System.out.printf("  起始位置: 轴0=%d, 轴1=%d%n", startPos[0].longValue(), startPos[1].longValue());
            System.out.printf("  前5个比较位置: %d, %d, %d, %d, %d%n",
                    cmpPos[0].longValue(), cmpPos[1].longValue(), cmpPos[2].longValue(),
                    cmpPos[3].longValue(), cmpPos[4].longValue());

            rtn = NMC_LinearCompSetData(devHandle, startPos, cmpPos, new NativeLong(dataCount), chn);
            checkError(rtn, "NMC_LinearCompSetData");
            if (rtn == RTN_CMD_SUCCESS) {
                System.out.println("✅ NMC_LinearCompSetData 执行成功");
            }

            // c. 启动线性位置比较输出
            System.out.println("\n=== 启动线性位置比较 ===");
            rtn = NMC_LinearCompOnOff(devHandle, (short) 1, chn);
            checkError(rtn, "NMC_LinearCompOnOff");
            if (rtn == RTN_CMD_SUCCESS) {
                System.out.println("✅ NMC_LinearCompOnOff (启动) 执行成功");
            }

            // d. 执行运动，触发位置比较
            // 运动第一个轴
            System.out.println("\n=== 执行运动并触发比较 ===");
            System.out.println("  开始执行 PTP 绝对运动...");

            rtn = NMC_MtMovePtpAbs(axisHandle, 1.0, 1.0, 0.0, 0.0, 5.0, (short) 0, new NativeLong(100000L));
            checkError(rtn, "NMC_MtMovePtpAbs");
            if (rtn == RTN_CMD_SUCCESS) {
                System.out.println("✅ NMC_MtMovePtpAbs 指令已发送");
            }

            // e. 等待运动完成并查询状态
            System.out.println("  等待运动完成...");
            ShortByReference pAxisSts = new ShortByReference();
            while (true) {
                rtn = NMC_MtGetSts(axisHandle, pAxisSts);
                checkError(rtn, "NMC_MtGetSts");
                if ((pAxisSts.getValue() & BIT_AXIS_BUSY) == 0) {
                    break;
                }
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                }
            }
            System.out.println("✅ 轴运动已完成");

            // f. 查询线性位置比较的状态
            ShortByReference pCompStatus = new ShortByReference(); // 0:停止, 1:运行
            ShortByReference pOutputCount = new ShortByReference(); // 已输出的点数

            System.out.println("\n=== 查询线性位置比较状态 ===");
            rtn = NMC_LinearCompStatus(devHandle, pCompStatus, pOutputCount, chn);
            checkError(rtn, "NMC_LinearCompStatus");

            short compStatus = pCompStatus.getValue();
            short outputCount = pOutputCount.getValue();

            System.out.printf("  比较器状态: %s (0=停止, 1=运行)%n", compStatus == 1 ? "运行中" : "已停止");
            System.out.printf("  已输出点数: %d%n", outputCount);

            // 简单判断：如果输出点数大于0，说明功能可能已生效
            if (outputCount > 0) {
                System.out.println("✅ 线性位置比较功能已产生输出，测试成功！");
            } else {
                System.out.println("❌ 线性位置比较功能未产生输出，请检查DO配置和硬件连接。");
            }


            /**
             * 结束测试，关闭设备
             */
            rtn = NMC_MtClose(pAxisHandle);
            checkError(rtn, "NMC_MtClose");
            rtn = NMC_DevClose(pDevHandle);
            checkError(rtn, "NMC_DevClose");

        }
    }
}