package com.elphel.imagej.gpu.jna;

import com.sun.jna.Library;
import com.sun.jna.Pointer;

/**
 * JNA boundary to the native tile-processor library (libtileproc.so) for the JCuda->JNA migration.
 * Stage-0b surface only: prove module compile/load across JNA. The full set (instances, set/exec/get)
 * follows the design doc handoffs/2026-06-25_JCuda-to-JNA-migration-design.md. By Claude on 2026-06-25.
 */
public interface TpJna extends Library {
    /** NVRTC-compile the kernels in srcdir (+ getTpDefines), cuLink(libcudadevrt), load the module.
     *  Returns an opaque module handle, or null on failure (see tp_last_error()). */
    Pointer tp_create_module(String srcdir, String libcudadevrt);
    /** Number of kernel functions resolved in the module (19 expected), or -1 if handle is null. */
    int     tp_module_num_functions(Pointer module);
    /** Last error message (NVRTC/CUDA log), empty if none. */
    String  tp_last_error();
    /** Free the module (cuModuleUnload + cuCtxDestroy). */
    void    tp_destroy_module(Pointer module);

    // ---- Stage 1: instance + geometry path ----
    /** Create a per-config GPU instance (allocates geometry device buffers). Null on failure. */
    Pointer tp_create_instance(Pointer module);
    /** Upload gc.expandSensors(16).toFloatArray() (n floats) to gpu_geometry_correction. 0 on success. */
    int     tp_set_geometry_correction(Pointer instance, float[] fgc, int n);
    /** Upload cv.toFullRollArray() (n floats) to gpu_correction_vector. 0 on success. */
    int     tp_set_correction_vector(Pointer instance, float[] fcv, int n);
    /** Run calcReverseDistortionTable -> gpu_rByRDist. 0 on success. */
    int     tp_exec_calc_reverse_distortions(Pointer instance);
    /** Run calc_rot_deriv(num_cams) -> gpu_rot_deriv. 0 on success. */
    int     tp_exec_rot_derivs(Pointer instance, int num_cams);
    /** Read gpu_rByRDist back into out[RBYRDIST_LEN=5001]. 0 on success. */
    int     tp_get_rbyrdist(Pointer instance, float[] out);
    /** Read gpu_rot_deriv back into out[5*16*3*3=720]. 0 on success. */
    int     tp_get_rot_deriv(Pointer instance, float[] out);
    /** Free the instance device buffers. */
    void    tp_destroy_instance(Pointer instance);

    // ---- Stage 2: convert_direct selftest ----
    /** Run the full convert_direct path (mirrors TpHostGpu allTests convert chain) against the
     *  tile_processor_gpu/clt golden data under data_root. lwir!=0 -> 16-cam LWIR set.
     *  Writes max |CLT-golden| into outMaxErr[0] and the kernel-computed active-tile count into
     *  outNumActive[0]. Returns 0 on success. */
    int     tp_convert_direct_selftest(Pointer module, int lwir, String data_root,
                                       double[] outMaxErr, int[] outNumActive);

    // ---- Stage 3: convert_direct + imclt_rbg_all ----
    /** Run convert_direct then imclt_rbg_all; compare CLT to clt/aux_chnN.clt (outCltErr[0]) and
     *  the de-pitched RBG to clt/aux_chnN.rbg (outRbgErr[0]). Returns 0 on success. */
    int     tp_imclt_selftest(Pointer module, int lwir, String data_root,
                              double[] outCltErr, double[] outRbgErr, int[] outNumActive);

    // ---- Stage 4: correlate2D + corr2D_combine + corr2D_normalize ----
    /** Run convert_direct then the intra TD-correlation quad path; compare CLT to clt/aux_chnN.clt
     *  (outCltErr[0]) and the quad-combined correlation to clt/aux_corr-quad.corr (outCorrErr[0]). */
    int     tp_corr_selftest(Pointer module, int lwir, String data_root,
                             double[] outCltErr, double[] outCorrErr, int[] outNumActive);
}
