package com.foxx.androidcast.media.codec.jni;

/*********************************************************************
 * NativeCodecBridge.java
 * Created at: Sun 17 May 2026 22:49:49 +0200
 * Updated at: Wed 20 May 2026 15:17:13 +0200 by Anton Afanasyeu <a.afanasieff@gmail.com>
 * Commit: 5d8e82d2e60a21fff3138d2a394ee4e8b4c6dcb8
 * class NativeCodecBridge
 * Contributors:
 *    - Anton Afanasyeu <a.afanasieff@gmail.com> (4 commits, 124 lines)
 *    - Cursor Agent (project assistant)
 * Digest: SHA256	bf3ba812b94838714e674811ced6549bad58071210e891174733e7b01ba499c3
**********************************************************************/
import android.util.Log;
import android.view.Surface;

/** JNI probes for third-party codecs built from {@code ndk/} + {@code third-party/}. */
public final class NativeCodecBridge {
    private static final String TAG = "NativeCodecBridge";
    private static final String LIB = "androidcast_codecs";

    private static boolean loaded;
    private static boolean loadAttempted;

    private NativeCodecBridge() {}

    public static boolean ensureLoaded() {
        if (loadAttempted) {
            return loaded;
        }
        loadAttempted = true;
        try {
            System.loadLibrary(LIB);
            loaded = true;
        } catch (UnsatisfiedLinkError e) {
            Log.w(TAG, "Native codec library not available: " + e.getMessage());
            loaded = false;
        }
        return loaded;
    }

    public static boolean isLibvpxAvailable() {
        return ensureLoaded() && nativeIsLibvpxAvailable();
    }

    public static boolean isOpusAvailable() {
        return ensureLoaded() && nativeIsOpusAvailable();
    }

    public static boolean isSpeexAvailable() {
        return ensureLoaded() && nativeIsSpeexAvailable();
    }

    public static long vpxEncoderCreate(String mime, int width, int height, int bitrateKbps) {
        if (!isLibvpxAvailable()) {
            return 0L;
        }
        return nativeVpxEncoderCreate(mime, width, height, bitrateKbps);
    }

    public static byte[] vpxEncodeYuv(long handle, byte[] i420, long ptsUs, boolean forceKeyframe) {
        VpxEncodedFrame frame = vpxEncodeYuvFrame(handle, i420, ptsUs, forceKeyframe);
        return frame != null ? frame.data : null;
    }

    public static VpxEncodedFrame vpxEncodeYuvFrame(long handle, byte[] i420, long ptsUs,
            boolean forceKeyframe) {
        if (handle == 0L || i420 == null) {
            return null;
        }
        return nativeVpxEncodeYuvFrame(handle, i420, ptsUs, forceKeyframe);
    }

    public static long vpxDecoderCreate(String mime) {
        if (!isLibvpxAvailable()) {
            return 0L;
        }
        return nativeVpxDecoderCreate(mime);
    }

    public static boolean vpxDecodeFrame(long handle, byte[] data, long ptsUs, Surface surface) {
        if (handle == 0L || data == null || surface == null) {
            return false;
        }
        return nativeVpxDecodeFrame(handle, data, ptsUs, surface);
    }

    public static void vpxDecoderRelease(long handle) {
        if (handle != 0L) {
            nativeVpxDecoderRelease(handle);
        }
    }

    public static void vpxEncoderRelease(long handle) {
        if (handle != 0L) {
            nativeVpxEncoderRelease(handle);
        }
    }

    public static void vpxRequestKeyframe(long handle) {
        if (handle != 0L) {
            nativeVpxRequestKeyframe(handle);
        }
    }

    private static native boolean nativeIsLibvpxAvailable();

    private static native boolean nativeIsOpusAvailable();

    private static native boolean nativeIsSpeexAvailable();

    private static native long nativeVpxEncoderCreate(String mime, int width, int height, int bitrateKbps);

    private static native byte[] nativeVpxEncodeYuv(long handle, byte[] yuv, long ptsUs, boolean forceKeyframe);

    private static native VpxEncodedFrame nativeVpxEncodeYuvFrame(long handle, byte[] yuv, long ptsUs,
            boolean forceKeyframe);

    private static native void nativeVpxEncoderRelease(long handle);

    private static native void nativeVpxRequestKeyframe(long handle);

    private static native long nativeVpxDecoderCreate(String mime);

    private static native boolean nativeVpxDecodeFrame(long handle, byte[] data, long ptsUs, Surface surface);

    private static native void nativeVpxDecoderRelease(long handle);
}
