package com.davoice.vad;

import com.davoice.vadetection.vadandroidlibrary.VADetection;
import com.facebook.react.bridge.*;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import androidx.annotation.Nullable;
import ai.onnxruntime.*;
import android.util.Log;
import java.util.HashMap;
import java.util.Map;

public class VADRNBridge extends ReactContextBaseJavaModule {

    private final String TAG = "VADetection";
    private static final String REACT_CLASS = "VADRNBridge";
    private static ReactApplicationContext reactContext;

    // Map to hold multiple instances
    private Map<String, VADetection> instances = new HashMap<>();

    public VADRNBridge(ReactApplicationContext context) {
        super(context);
        Log.d(TAG, "VADRNBridge constructor");
        reactContext = context;
    }

    @Override
    public String getName() {
        return REACT_CLASS;
    }

    @ReactMethod
    public void setVADDetectionLicense(String instanceId, String licenseKey, Promise promise) {
        Log.d(TAG, "setVADDetectionLicense()");

        VADetection instance = instances.get(instanceId);
        boolean isLicensed = false;
        if (instance != null) {
            isLicensed = instance.setLicenseKey(licenseKey);
        }
        else {
            Log.e(TAG, "instance == null!!!! ");
        }

        Log.d(TAG, "setVADDetectionLicense(): " + (isLicensed ? "Licensed" : "Not Licensed"));
        promise.resolve(isLicensed);
    }

    @ReactMethod
    public void __setVADDetectionLicense(String instanceId, String licenseKey, Promise promise) {
        Log.d(TAG, "setVADDetectionLicense()");
        Log.d(TAG, "setVADDetectionLicense()");
        Log.d(TAG, "setVADDetectionLicense()");
        VADetection instance = instances.get(instanceId);
        Log.d(TAG, "setVADDetectionLicense()");
        Log.d(TAG, "setVADDetectionLicense()");
        Log.d(TAG, "setVADDetectionLicense()");

        int isLicesed = 0;
        if (instance != null) {
            boolean isLic = instance.setLicenseKey(licenseKey);
            isLicesed = isLic ? 1:0;
        }
        Log.d(TAG, "setVADetectionLicense(): " + (isLicesed == 0 ? "Licensed" : "Not Licensed"));

        promise.resolve("isLicesed: " + isLicesed);
    }

    // Create a new instance
    @ReactMethod
    public void createInstance(String instanceId, float threshold, int msWindow, Promise promise) {
        Log.d(TAG, "createInstance(): ");

        if (instances.containsKey(instanceId)) {
            promise.reject("InstanceExists", "Instance already exists with ID: " + instanceId);
            return;
        }
        Log.d(TAG, "createInstance(): 2");

        try {
            VADetection instance = new VADetection(reactContext, threshold, msWindow);
            Log.d(TAG, "createInstance(): 3 VADetection: " + instance);
            Log.d(TAG, "createInstance(): 3 instanceId: " + instanceId);
            instances.put(instanceId, instance);
            promise.resolve("Instance created with ID: " + instanceId);
        } catch (Exception e) {
            Log.e(TAG, "Exception(): 3 VADetection = new VADetection: ");
            promise.reject("CreateError", "Failed to create instance: " + e.getMessage());
        }
    }

    // Start detection for a specific instance
    @ReactMethod
    public void startVADDetection(String instanceId, Promise promise) {
        for (Map.Entry<String, VADetection> entry : instances.entrySet()) {
            String key = entry.getKey();
            VADetection value = entry.getValue();
            Log.d(TAG, "Key: " + key + ", Value: " + value.toString());
        }

        VADetection instance = this.instances.get(instanceId);
        if (instance != null) {
            instance.startListening();
            promise.resolve("Started detection for instance: " + instanceId);
        } else {
            promise.reject("InstanceNotFound", "No instance found with ID: " + instanceId);
        }
    }

    // Stop detection for a specific instance
    @ReactMethod
    public void stopForegroundService(String instanceId, Promise promise) {
        VADetection instance = instances.get(instanceId);
        if (instance != null) {
            instance.stopForegroundService();
            promise.resolve("stopForegroundService" + instanceId);
        } else {
            promise.reject("stopForegroundService", "No instance found with ID: " + instanceId);
        }
    }
    
    // Stop detection for a specific instance
    @ReactMethod
    public void startForegroundService(String instanceId, Promise promise) {
        VADetection instance = instances.get(instanceId);
        if (instance != null) {
            instance.startForegroundService();
            promise.resolve("startForegroundService" + instanceId);
        } else {
            promise.reject("startForegroundService", "No instance found with ID: " + instanceId);
        }
    }

    @ReactMethod
    public void getVoiceProps(String instanceId, Promise promise) {
        VADetection instance = instances.get(instanceId);
        if (instance != null) {
            try {
                Map<String, Object> voiceProps = instance.getVoiceProps();
                WritableMap result = Arguments.createMap();

                result.putString("error", (String) voiceProps.get("error"));
                result.putDouble("voiceProbability", (float) voiceProps.get("voiceProbability"));
                result.putDouble("lastTimeHumanVoiceHeard", (long) voiceProps.get("lastTimeHumanVoiceHeard"));

                promise.resolve(result);
            } catch (Exception e) {
                promise.reject("VoicePropsError", "Failed to get voice properties: " + e.getMessage());
            }
        } else {
            promise.reject("InstanceNotFound", "No instance found with ID: " + instanceId);
        }
    }

    // Stop detection for a specific instance
    @ReactMethod
    public void stopVADDetection(String instanceId, Promise promise) {
        VADetection instance = instances.get(instanceId);
        if (instance != null) {
            instance.stopListening();
            promise.resolve("Stopped detection for instance: " + instanceId);
        } else {
            promise.reject("InstanceNotFound", "No instance found with ID: " + instanceId);
        }
    }

    // Destroy an instance
    @ReactMethod
    public void destroyInstance(String instanceId, Promise promise) {
        VADetection instance = instances.remove(instanceId);
        if (instance != null) {
            instance.stopListening();
            // Additional cleanup if necessary
            promise.resolve("Destroyed instance: " + instanceId);
        } else {
            promise.reject("InstanceNotFound", "No instance found with ID: " + instanceId);
        }
    }

    // Handle vad detection event
    private void onVADetected(String instanceId, Boolean detected) {
        if (detected) {
            WritableMap params = Arguments.createMap();
            params.putString("instanceId", instanceId);
            params.putString("phrase", instanceId);
            sendEvent("onVADetectionEvent", params);
        }
    }

    // Send event to JavaScript
    private void sendEvent(String eventName, @Nullable WritableMap params) {
        reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
            .emit(eventName, params);
    }

    @ReactMethod
    public void addListener(String eventName) {
        // Set up any upstream listeners or background tasks as necessary
    }

    @ReactMethod
    public void removeListeners(Integer count) {
        // Remove upstream listeners, stop unnecessary background tasks
    }
    // Implement other methods as needed, ensuring to use instanceId
}

