package com.reactnativevstarcam;

import android.view.View;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.annotations.ReactProp;

import java.util.Map;

/**
 * React Native ViewManager for VStarCamVideoView.
 * Exposes the native video view as a React component.
 */
@ReactModule(name = VStarCamVideoViewManager.REACT_CLASS)
public class VStarCamVideoViewManager extends SimpleViewManager<VStarCamVideoView> {
    public static final String REACT_CLASS = "VStarCamVideoView";
    
    // Command IDs for direct commands from JS
    public static final int COMMAND_START_STREAM = 1;
    public static final int COMMAND_STOP_STREAM = 2;
    public static final int COMMAND_CAPTURE_SNAPSHOT = 3;

    @NonNull
    @Override
    public String getName() {
        return REACT_CLASS;
    }

    @NonNull
    @Override
    protected VStarCamVideoView createViewInstance(@NonNull ThemedReactContext reactContext) {
        return new VStarCamVideoView(reactContext);
    }

    /**
     * Set the client pointer for the video stream
     */
    @ReactProp(name = "clientPtr")
    public void setClientPtr(VStarCamVideoView view, double clientPtr) {
        // React Native passes numbers as doubles, convert to long
        view.setClientPtr((long) clientPtr);
    }

    /**
     * Set the video resolution
     * 1 = high, 2 = general/default, 4 = low, 100 = superHD
     */
    @ReactProp(name = "resolution", defaultInt = 2)
    public void setResolution(VStarCamVideoView view, int resolution) {
        view.setResolution(resolution);
    }

    /**
     * Control streaming via prop
     */
    @ReactProp(name = "streaming", defaultBoolean = false)
    public void setStreaming(VStarCamVideoView view, boolean streaming) {
        if (streaming) {
            view.startStream();
        } else {
            view.stopStream();
        }
    }

    /**
     * Commands that can be called from JS via dispatchViewManagerCommand
     */
    @Nullable
    @Override
    public Map<String, Integer> getCommandsMap() {
        return MapBuilder.of(
            "startStream", COMMAND_START_STREAM,
            "stopStream", COMMAND_STOP_STREAM,
            "captureSnapshot", COMMAND_CAPTURE_SNAPSHOT
        );
    }

    // Handle commands dispatched with NUMERIC IDs (from UIManager.Commands)
    @Override
    public void receiveCommand(@NonNull VStarCamVideoView view, int commandId, @Nullable ReadableArray args) {
        switch (commandId) {
            case COMMAND_START_STREAM:
                view.startStream();
                break;
            case COMMAND_STOP_STREAM:
                view.stopStream();
                break;
            case COMMAND_CAPTURE_SNAPSHOT:
                if (args != null && args.size() > 0) {
                    view.captureSnapshot(args.getString(0));
                }
                break;
        }
    }

    // Handle commands dispatched with STRING IDs (legacy/fallback)
    @Override
    public void receiveCommand(@NonNull VStarCamVideoView view, String commandId, @Nullable ReadableArray args) {
        switch (commandId) {
            case "startStream":
                view.startStream();
                break;
            case "stopStream":
                view.stopStream();
                break;
            case "captureSnapshot":
                if (args != null && args.size() > 0) {
                    view.captureSnapshot(args.getString(0));
                }
                break;
        }
    }

    /**
     * Events that can be sent to JS
     */
    @Nullable
    @Override
    public Map<String, Object> getExportedCustomDirectEventTypeConstants() {
        return MapBuilder.<String, Object>builder()
            .put("onStreamStarted", MapBuilder.of("registrationName", "onStreamStarted"))
            .put("onStreamStopped", MapBuilder.of("registrationName", "onStreamStopped"))
            .put("onStreamError", MapBuilder.of("registrationName", "onStreamError"))
            .put("onFrameReceived", MapBuilder.of("registrationName", "onFrameReceived"))
            .build();
    }
}
