package com.reactnativezoom.videosdk.broadcaststream;

import android.content.Context;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.util.AttributeSet;

import us.zoom.rawdatarender.RawDataBufferType;
import us.zoom.rawdatarender.ZoomSurfaceViewRender;
import us.zoom.sdk.ZoomVideoSDKBroadcastStreamingVideoCallback;
import us.zoom.sdk.ZoomVideoSDKVideoRawData;

/**
 * Renders incoming broadcast video frames (I420 YUV byte arrays) onto an
 * OpenGL surface via the SDK's {@link ZoomSurfaceViewRender} base class.
 *
 * Adapted from the Zoom Android sample's BroadcastingStreamVideoRenderer.
 * The base class owns the GL surface and YUV-to-RGB shader pipeline; we
 * just feed it byte arrays from the SDK's
 * {@link ZoomVideoSDKBroadcastStreamingVideoCallback} callback.
 */
public class BroadcastStreamingVideoRenderer extends ZoomSurfaceViewRender
        implements ZoomVideoSDKBroadcastStreamingVideoCallback {

    private static HandlerThread handlerThread;
    private static Handler handler;

    public BroadcastStreamingVideoRenderer(Context context) {
        super(context);
        init();
    }

    public BroadcastStreamingVideoRenderer(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        setBufferType(RawDataBufferType.BYTE_ARRAY);
        initRender();
        startRender();
        if (handlerThread == null) {
            handlerThread = new HandlerThread("BroadcastStreamingRawDataRenderer");
            handlerThread.start();
            handler = new Handler(handlerThread.getLooper());
        }
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        startRender();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        // Stops the GL render loop. Subscribe/unsubscribe is owned by the
        // parent View; we just release rendering resources here.
        stopRender();
    }

    @Override
    public void onVideoFrameReceived(ZoomVideoSDKVideoRawData rawData) {
        if (rawData == null) {
            return;
        }
        boolean isMainThread = Thread.currentThread() == Looper.getMainLooper().getThread();
        if (isMainThread && rawData.canAddRef()) {
            rawData.addRef();
            handler.post(new Runnable() {
                @Override
                public void run() {
                    drawI420YUV(rawData.getyBuffer(), rawData.getuBuffer(), rawData.getvBuffer(),
                            rawData.getStreamWidth(), rawData.getStreamHeight(),
                            rawData.getRotation(), 30);
                    rawData.releaseRef();
                }
            });
        } else {
            drawI420YUV(rawData.getyBuffer(), rawData.getuBuffer(), rawData.getvBuffer(),
                    rawData.getStreamWidth(), rawData.getStreamHeight(),
                    rawData.getRotation(), 30);
        }
    }
}
