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);
        }
    }

    /**
     * 建立坐标系
     */
    private static void crdBuild(HAND devHandle, HAND crdHandle) {
        System.out.println("=== 建立坐标系 ===");
        short rtn = NMC_CrdConfig(crdHandle, new TCrdConfig() {{
            axCnts = 2;
            pAxArray[0] = 0; // X轴
            pAxArray[1] = 1; // Y轴
            pAxArray[2] = -1;
            pAxArray[3] = -1;
            port[0] = 0;
            port[1] = 0;
            port[2] = 0;
            port[3] = 0;
        }});
        checkError(rtn, "NMC_CrdConfig");
        if (rtn != RTN_CMD_SUCCESS) return;

        TCrdPara crdPara = new TCrdPara();
        crdPara.orgFlag = 1;
        crdPara.offset[0] = 0;
        crdPara.offset[1] = 0;
        crdPara.offset[2] = 0;
        crdPara.offset[3] = 0;
        crdPara.synAccMax = 50.0;
        crdPara.synVelMax = 800.0;
        rtn = NMC_CrdSetPara(crdHandle, crdPara);
        checkError(rtn, "NMC_CrdSetPara");

        TCrdSafePara crdSafePara = new TCrdSafePara();
        crdSafePara.estpDec = 1000;
        crdSafePara.maxAcc = 50;
        crdSafePara.maxVel = 800;
        rtn = NMC_CrdSetSafePara(crdHandle, crdSafePara);
        checkError(rtn, "NMC_CrdSetSafePara");

        rtn = NMC_CrdClrError(crdHandle);
        checkError(rtn, "NMC_CrdClrError");
        rtn = NMC_CrdBufClr(crdHandle);
        checkError(rtn, "NMC_CrdBufClr");
    }

    /**
     * 压入直线插补数据
     */
    private static void crdLineInter(HAND crdHandle) {
        System.out.println("=== 压入直线插补数据 ===");
        NativeLong[] tgPos = new NativeLong[2];

        tgPos[0] = new NativeLong(10000);
        tgPos[1] = new NativeLong(10000);
        short rtn = NMC_CrdLineXYZEx(crdHandle, new NativeLong(0), (short)0x03, tgPos, 0.0, 10.0, 0.5, (short)0);
        checkError(rtn, "NMC_CrdLineXYZEx (1)");

        tgPos[0] = new NativeLong(50000);
        tgPos[1] = new NativeLong(60000);
        rtn = NMC_CrdLineXYZEx(crdHandle, new NativeLong(0), (short)0x03, tgPos, 0.0, 10.0, 0.5, (short)0);
        checkError(rtn, "NMC_CrdLineXYZEx (2)");
    }

    /**
     * 设置高速二维位置比较
     */
    private static void setHsio(HAND devHandle) {
        System.out.println("=== 设置高速二维位置比较 ===");
        TComp2DimensParam compara2d = new TComp2DimensParam();

        // 先关闭，再设置
        short rtn = NMC_Comp2DimensOnoff(devHandle, (short)0, (short)0, (short)0);
        checkError(rtn, "NMC_Comp2DimensOnoff (Stop)");

        // 配置参数
        compara2d.dir1No = 0; // X轴
        compara2d.dir2No = 1; // Y轴
        compara2d.chnType[0] = 1; // HSIO
        compara2d.chnType[1] = 0; // GPO
        compara2d.chnType[2] = 0; // GPO
        compara2d.outputType[0] = 0; // 脉冲
        compara2d.outputType[1] = 0; // 电平
        compara2d.outputType[2] = -1; // 不处理
        compara2d.outputchn[0] = 0; // DO0
        compara2d.outputchn[1] = -1;
        compara2d.outputchn[2] = -1;
        compara2d.errZone = 20;
        compara2d.gateTime[0] = 10; // us
        compara2d.gateTime[1] = 10;
        compara2d.gateTime[2] = 10;
        compara2d.posSrc = 1; // 编码器
        compara2d.stLevel[0] = 0; // 低电平

        rtn = NMC_Comp2DimensSetParam(devHandle, (short)0, compara2d, (short)0);
        checkError(rtn, "NMC_Comp2DimensSetParam");

        // 设置数据
        int count = 2;
        NativeLong[] compos = new NativeLong[2 * count];
        for (int i = 0; i < count; i++) {
            compos[i * 2 + 0] = new NativeLong(100L * i + 100L); // X
            compos[i * 2 + 1] = new NativeLong(100L * i + 100L); // Y
        }

        // 先清空再设置
        rtn = NMC_Comp2DimensSetData(devHandle, (short)0, compos, (short)0, (short)0);
        checkError(rtn, "NMC_Comp2DimensSetData (Clear)");
        rtn = NMC_Comp2DimensSetData(devHandle, (short)0, compos, (short)count, (short)0);
        checkError(rtn, "NMC_Comp2DimensSetData (Set)");

        // 启动
        rtn = NMC_Comp2DimensOnoff(devHandle, (short)0, (short)1, (short)0);
        checkError(rtn, "NMC_Comp2DimensOnoff (Start)");
    }

    /**
     * 启动坐标系运动并等待完成
     */
    private static void crdStart(HAND crdHandle) {
        System.out.println("=== 启动坐标系运动 ===");
        short rtn = NMC_CrdEndMtn(crdHandle);
        checkError(rtn, "NMC_CrdEndMtn");
        rtn = NMC_CrdStartMtn(crdHandle);
        checkError(rtn, "NMC_CrdStartMtn");

        System.out.println("等待运动完成...");
        ShortByReference pSts = new ShortByReference();
        while (true) {
            rtn = NMC_CrdGetSts(crdHandle, pSts);
            checkError(rtn, "NMC_CrdGetSts");
            if ((pSts.getValue() & BIT_CORD_BUSY) == 0) {
                break;
            }
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                break;
            }
        }
        System.out.println("✅ 运动已完成");
    }

    /**
     * 主函数：执行全部流程
     */
    public static void main(String[] args) {
        short devNum = 0;
        PHAND pDevHandle = new PHAND();
        PHAND pCrdHandle = new PHAND();

        short rtn = NMC_DevOpen(devNum, pDevHandle);
        checkError(rtn, "NMC_DevOpen");
        if (rtn != RTN_CMD_SUCCESS) return;
        HAND devHandle = pDevHandle.getHandle();

        rtn = NMC_CrdOpen(devHandle, pCrdHandle);
        checkError(rtn, "NMC_CrdOpen");
        if (rtn != RTN_CMD_SUCCESS) return;
        HAND crdHandle = pCrdHandle.getHandle();

        try {
            crdBuild(devHandle, crdHandle);
            crdLineInter(crdHandle);
            setHsio(devHandle);
            crdStart(crdHandle);
        } finally {
            NMC_CrdClose(pCrdHandle);
            NMC_DevClose(pDevHandle);
        }

        System.out.println("XY轴坐标系运动高速二维位置比较测试完成。");
    }
}