package com.reactnativezoom.videosdk;

import android.app.Activity;
import androidx.fragment.app.FragmentActivity;
import android.view.Choreographer;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.ThemedReactContext;

import us.zoom.sdk.ZoomVideoSDK;
import us.zoom.sdk.ZoomVideoSDKErrors;
import us.zoom.sdk.ZoomVideoSDKShareHelper;
import us.zoom.sdk.ZoomVideoSDKWhiteboardHelper;
import android.util.Log;

/**
 * Custom FrameLayout that ensures child views are properly measured and laid out.
 * This is needed for React Native to properly render Fragment-based views.
 */
class WhiteboardFrameLayout extends FrameLayout {
  private static final String TAG = "WhiteboardFrameLayout";
  private Choreographer.FrameCallback frameCallback;
  private boolean isFrameCallbackActive = false;

  public WhiteboardFrameLayout(android.content.Context context) {
    super(context);
  }

  @Override
  public void requestLayout() {
    super.requestLayout();
    post(measureAndLayoutRunnable);
  }

  private final Runnable measureAndLayoutRunnable = new Runnable() {
    @Override
    public void run() {
      int width = getWidth();
      int height = getHeight();
      if (width > 0 && height > 0) {
        measure(
            View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
            View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY)
        );
        layout(getLeft(), getTop(), getRight(), getBottom());
        for (int i = 0; i < getChildCount(); i++) {
          View child = getChildAt(i);
          if (child.getWidth() == 0 || child.getHeight() == 0) {
            child.measure(
                View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
                View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY)
            );
            child.layout(0, 0, width, height);
          }
        }
      }
    }
  };

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

  @Override
  protected void onDetachedFromWindow() {
    super.onDetachedFromWindow();
    stopFrameCallback();
  }

  private void startFrameCallback() {
    if (isFrameCallbackActive) {
      return;
    }
    isFrameCallbackActive = true;
    frameCallback = new Choreographer.FrameCallback() {
      @Override
      public void doFrame(long frameTimeNanos) {
        if (!isFrameCallbackActive) {
          return;
        }
        int width = getMeasuredWidth();
        int height = getMeasuredHeight();
        if (width > 0 && height > 0) {
          for (int i = 0; i < getChildCount(); i++) {
            View child = getChildAt(i);
            if (child.getWidth() == 0 || child.getHeight() == 0) {
              child.measure(
                  View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
                  View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY)
              );
              child.layout(0, 0, width, height);
            }
          }
        }
        Choreographer.getInstance().postFrameCallback(this);
      }
    };
    Choreographer.getInstance().postFrameCallback(frameCallback);
  }

  private void stopFrameCallback() {
    if (!isFrameCallbackActive) {
      return;
    }
    isFrameCallbackActive = false;
    if (frameCallback != null) {
      Choreographer.getInstance().removeFrameCallback(frameCallback);
      frameCallback = null;
    }
  }
}

public class RNZoomWhiteboardViewManager extends SimpleViewManager<FrameLayout> {

  private final ReactApplicationContext reactContext;
  public static RNZoomWhiteboardViewManager instance;
  public static FrameLayout whiteboardView;

  public RNZoomWhiteboardViewManager(ReactApplicationContext reactContext) {
    this.reactContext = reactContext;
  }

  public static RNZoomWhiteboardViewManager createInstance(ReactApplicationContext reactContext) {
    if (instance == null) {
      instance = new RNZoomWhiteboardViewManager(reactContext);
    }
    return instance;
  }

  public static RNZoomWhiteboardViewManager getInstance() {
    return instance;
  }

  @Override
  public String getName() {
    return "RNZoomWhiteboardView";
  }

  @Override
  protected FrameLayout createViewInstance(ThemedReactContext themedReactContext) {
    whiteboardView = new WhiteboardFrameLayout(themedReactContext);
    whiteboardView.setId(whiteboardView.hashCode());
    whiteboardView.setBackgroundColor(0x00000000);
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
      whiteboardView.setElevation(10.0f);
    }
    FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
        FrameLayout.LayoutParams.MATCH_PARENT,
        FrameLayout.LayoutParams.MATCH_PARENT
    );
    whiteboardView.setLayoutParams(layoutParams);

    whiteboardView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
      @Override
      public void onGlobalLayout() {
        whiteboardView.getViewTreeObserver().removeOnGlobalLayoutListener(this);

        whiteboardView.post(new Runnable() {
          @Override
          public void run() {
            Activity activity = reactContext.getCurrentActivity();
            if (activity != null) {
              activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                  subscribeWhiteboard();
                }
              });
            }
          }
        });
      }
    });

    return whiteboardView;
  }

  public void subscribeWhiteboard() {
    try {
      ZoomVideoSDKShareHelper shareHelper = ZoomVideoSDK.getInstance().getShareHelper();
      if (shareHelper == null) {
        Log.e("whiteboard", "shareHelper is null");
        return;
      }

      ZoomVideoSDKWhiteboardHelper whiteboardHelper = shareHelper.getWhiteboardHelper();
      if (whiteboardHelper == null) {
        Log.e("whiteboard", "whiteboardHelper is null");
        return;
      }

      Activity activity = reactContext.getCurrentActivity();
      if (!(activity instanceof FragmentActivity)) {
        Log.e("whiteboard", "activity is not FragmentActivity");
        return;
      }
      FragmentActivity fragmentActivity = (FragmentActivity) activity;

      if (whiteboardView != null) {
        int res = whiteboardHelper.subscribeWhiteboard(fragmentActivity, whiteboardView);
        if (res != ZoomVideoSDKErrors.Errors_Success) {
          Log.e("whiteboard", "subscribeWhiteboard failed with error: " + res);
        }
      } else {
        Log.e("whiteboard", "whiteboardView is null");
      }
    } catch (Exception e) {
      Log.e("whiteboard", "Exception in subscribeWhiteboard", e);
      e.printStackTrace();
    }
  }

  public void unsubscribeWhiteboard() {
    try {
      ZoomVideoSDKShareHelper shareHelper = ZoomVideoSDK.getInstance().getShareHelper();
      if (shareHelper == null) {
        return;
      }
      ZoomVideoSDKWhiteboardHelper whiteboardHelper = shareHelper.getWhiteboardHelper();
      if (whiteboardHelper == null) {
        return;
      }

      Activity activity = reactContext.getCurrentActivity();
      if (!(activity instanceof FragmentActivity)) {
        return;
      }
      FragmentActivity fragmentActivity = (FragmentActivity) activity;

      whiteboardHelper.unSubscribeWhiteboard(fragmentActivity);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

}
