package com.foxx.androidcast.entitlements;

import android.util.Log;

/**
 * Loads {@code libandroidcast_entitlements.so} on demand. If load fails, callers must assume zero paid
 * flags (unless dev unlock-all is enabled at the Java layer).
 */
public final class EntitlementNativeBridge {
    private static final String TAG = "EntitlementNative";
    static final String LIB = "androidcast_entitlements";

    private static final Object LOCK = new Object();
    private static int refCount = 0;
    private static boolean loaded = false;
    private static boolean loadFailed = false;

    private EntitlementNativeBridge() {}

    public static void acquire() {
        synchronized (LOCK) {
            if (loadFailed) {
                return;
            }
            if (!loaded) {
                try {
                    System.loadLibrary(LIB);
                    loaded = true;
                } catch (UnsatisfiedLinkError e) {
                    loadFailed = true;
                    Log.w(TAG, "Native entitlements library unavailable: " + e.getMessage());
                    return;
                }
            }
            refCount++;
        }
    }

    public static void release() {
        synchronized (LOCK) {
            if (refCount <= 0) {
                return;
            }
            refCount--;
            if (refCount == 0) {
                loaded = false;
            }
        }
    }

    public static boolean isAvailable() {
        synchronized (LOCK) {
            return loaded && !loadFailed;
        }
    }

    public static boolean ensureLoaded() {
        acquire();
        boolean ok = isAvailable();
        if (!ok) {
            release();
        }
        return ok;
    }

    static void requireLoaded() {
        if (!isAvailable()) {
            throw new IllegalStateException("libandroidcast_entitlements is not loaded");
        }
    }

    public static int readFrom(String absolutePath, long key, long[] outVal) {
        requireLoaded();
        if (outVal == null || outVal.length < 1) {
            return -1;
        }
        return nativeReadFrom(absolutePath, key, outVal);
    }

    public static int writeTo(String absolutePath, long val, long key) {
        requireLoaded();
        return nativeWriteTo(absolutePath, val, key);
    }

    public static int decode(long encodedVal, long key, long[] outVal) {
        requireLoaded();
        if (outVal == null || outVal.length < 1) {
            return -1;
        }
        return nativeDecode(encodedVal, key, outVal);
    }

    public static int encode(long val, long key, long[] outEncoded) {
        requireLoaded();
        if (outEncoded == null || outEncoded.length < 1) {
            return -1;
        }
        return nativeEncode(val, key, outEncoded);
    }

    private static native int nativeReadFrom(String path, long key, long[] outVal);
    private static native int nativeWriteTo(String path, long val, long key);
    private static native int nativeDecode(long encodedVal, long key, long[] outVal);
    private static native int nativeEncode(long val, long key, long[] outEncoded);
}
