package com.reactnativezoom.videosdk;

import android.app.Service;
import android.content.Context;
import android.hardware.display.DisplayManager;
import android.os.Handler;
import android.os.Looper;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;

import java.util.List;
import java.util.Objects;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.reactnativezoom.videosdk.convert.RNZoomVideoSdkVideoAspect;
import com.reactnativezoom.videosdk.convert.RNZoomVideoSdkVideoResolution;

import us.zoom.sdk.ZoomVideoSDK;
import us.zoom.sdk.ZoomVideoSDKAnnotationHelper;
import us.zoom.sdk.ZoomVideoSDKUser;
import us.zoom.sdk.ZoomVideoSDKVideoAspect;
import us.zoom.sdk.ZoomVideoSDKVideoCanvas;
import us.zoom.sdk.ZoomVideoSDKVideoResolution;
import us.zoom.sdk.ZoomVideoSDKVideoView;
import us.zoom.sdk.ZoomVideoSDKVideoHelper;
import us.zoom.sdk.ZoomVideoSDKShareStatus;
import us.zoom.sdk.ZoomVideoSDKShareAction;


public class RNZoomViewManager extends SimpleViewManager<ZoomVideoSDKVideoView>  {

  private final ReactApplicationContext reactContext;
  public ZoomVideoSDKVideoView videoView;
  public ZoomVideoSDKAnnotationHelper annotationHelper;
  private ZoomVideoSDKVideoCanvas currentCanvas;
  private String userId;
  private boolean sharing;
  private ZoomVideoSDKVideoAspect videoAspect;
  private ZoomVideoSDKVideoResolution videoResolution;
  private boolean preview;
  private boolean hasMultiCamera;
  private String multiCameraIndex;
  public static RNZoomViewManager instance;
  private View annotationView;
  private int currentRotation;
  protected Display display;
  protected DisplayMetrics displayMetrics;
  protected Handler handler = new Handler(Looper.getMainLooper());

  public RNZoomViewManager(ReactApplicationContext reactContext) {
    this.reactContext = reactContext;
    DisplayManager displayManager = (DisplayManager) reactContext.getSystemService(Context.DISPLAY_SERVICE);
    displayManager.registerDisplayListener(mDisplayListener, handler);
    display = ((WindowManager) reactContext.getSystemService(Service.WINDOW_SERVICE)).getDefaultDisplay();
    displayMetrics = new DisplayMetrics();
    display.getMetrics(displayMetrics);
    currentRotation = -1;
  }

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

  public static RNZoomViewManager getInstance() {
    return instance;
  }

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

  @Override
  protected ZoomVideoSDKVideoView createViewInstance(ThemedReactContext reactContext) {
    userId = "";
    sharing = false;
    preview = false;
    hasMultiCamera = false;
    multiCameraIndex = "";
    videoAspect = ZoomVideoSDKVideoAspect.ZoomVideoSDKVideoAspect_Original;
    videoResolution = ZoomVideoSDKVideoResolution.ZoomVideoSDKResolution_Auto;
    videoView = new ZoomVideoSDKVideoView(reactContext);
    videoView.setZOrderMediaOverlay(true);
    return videoView;
  }

  @ReactProp(name = "userId")
  public void setUserId(ZoomVideoSDKVideoView videoView, String newUserId) {
    if (newUserId.equals(userId)) {
      return;
    }
    userId = newUserId;
    setViewingCanvas();
  }

  @ReactProp(name = "sharing")
  public void setSharing(ZoomVideoSDKVideoView videoView, boolean newSharing) {
    if (sharing == newSharing) {
      return;
    }
    sharing = newSharing;
    if (ZoomVideoSDK.getInstance().getShareHelper().isAnnotationFeatureSupport()) {
      if (sharing && annotationHelper == null) {
        ZoomVideoSDKUser mySelf = ZoomVideoSDK.getInstance().getSession().getMySelf();
        if (userId == mySelf.getUserID()) {
          annotationHelper = ZoomVideoSDK.getInstance().getShareHelper().createAnnotationHelper(null);
        } else {
          annotationHelper = ZoomVideoSDK.getInstance().getShareHelper().createAnnotationHelper(videoView);
        }
        if (annotationHelper != null) {
          annotationView = annotationHelper.getAnnotationView();
        }
        if (annotationView != null && annotationView.getParent() == null) {
          videoView.addView(annotationView);
        }
      } else {
        if (annotationView != null) {
          if (annotationView.getParent() != null) videoView.removeView(annotationView);
          annotationView = null;
        }
        if (annotationHelper != null) {
          ZoomVideoSDK.getInstance().getShareHelper().destroyAnnotationHelper(annotationHelper);
        }
      }
    }
    setViewingCanvas();
  }

  @ReactProp(name = "hasMultiCamera")
  public void setHasMultiCamera(ZoomVideoSDKVideoView videoView, boolean newHasMultiCamera) {
    if (hasMultiCamera == newHasMultiCamera) {
      return;
    }
    hasMultiCamera = newHasMultiCamera;
  }

  @ReactProp(name = "multiCameraIndex")
  public void setMultiCameraIndex(ZoomVideoSDKVideoView videoView, String newIndex) {
    if (multiCameraIndex == newIndex) {
      return;
    }
    multiCameraIndex = newIndex;
    setViewingCanvas();
  }

  @ReactProp(name = "fullScreen")
  public void setFullScreen(ZoomVideoSDKVideoView videoView, Boolean fullScreen) {
    videoView.setZOrderOnTop(!fullScreen);
  }

  @ReactProp(name = "videoAspect")
  public void setAspect(ZoomVideoSDKVideoView videoView, String newVideoAspect) {
    ZoomVideoSDKVideoAspect aspect = RNZoomVideoSdkVideoAspect.valueOf(newVideoAspect);
    if (videoAspect == aspect) {
      return;
    }
    videoAspect = aspect;
    setViewingCanvas();
  }

  @ReactProp(name = "videoResolution")
  public void setResolution(ZoomVideoSDKVideoView videoView, String newVideoResolution) {
    ZoomVideoSDKVideoResolution resolution = RNZoomVideoSdkVideoResolution.valueOf(newVideoResolution);
    if (videoResolution == resolution) {
      return;
    }
    videoResolution = resolution;
    setViewingCanvas();
  }

  @ReactProp(name = "preview")
  public void setPreview(ZoomVideoSDKVideoView videoView, boolean newPreview) {
    if (preview == newPreview) {
      return;
    }
    preview = newPreview;

    ZoomVideoSDKVideoHelper videoHelper = ZoomVideoSDK.getInstance().getVideoHelper();
    if (preview && currentCanvas == null) {
      videoHelper.startVideoCanvasPreview(videoView, videoAspect);
    } else {
      videoHelper.stopVideoCanvasPreview(videoView);
    }
  }

  private void setViewingCanvas()
  {
    ZoomVideoSDKUser user = RNZoomVideoSdkUserModule.getUser(userId);
    if (user == null) return;
    if (currentCanvas != null) {
      currentCanvas.unSubscribe(videoView);
      currentCanvas = null;
    }

    ZoomVideoSDKShareAction shareAction = null;
    ZoomVideoSDKUser mySelf = ZoomVideoSDK.getInstance().getSession().getMySelf();

    if (sharing) {
      if (!Objects.equals(userId, mySelf.getUserID())) {
        List<ZoomVideoSDKShareAction> list = user.getShareActionList();
        if (!list.isEmpty()) {
          for (ZoomVideoSDKShareAction action : list) {
            ZoomVideoSDKShareStatus shareStatus = action.getShareStatus();
            if ((shareStatus == ZoomVideoSDKShareStatus.ZoomVideoSDKShareStatus_Start || shareStatus == ZoomVideoSDKShareStatus.ZoomVideoSDKShareStatus_Resume) && action.getShareSourceId() != 0) {
              shareAction = action;
              break;
            }
          }
        }
        if (null != shareAction) {
          currentCanvas = shareAction.getShareCanvas();
        }
      }
    } else if (hasMultiCamera) {
        List<ZoomVideoSDKVideoCanvas> multiCameraList = user.getMultiCameraCanvasList();
        int index = Integer.parseInt(multiCameraIndex);
        currentCanvas = multiCameraList.get(index);
    } else {
      currentCanvas = user.getVideoCanvas();
    }
    if (!(Objects.equals(userId, mySelf.getUserID()) && sharing) && currentCanvas != null) {
      currentCanvas.subscribe(videoView, videoAspect, videoResolution);
    }
  }

  DisplayManager.DisplayListener mDisplayListener = new DisplayManager.DisplayListener() {
    @Override
    public void onDisplayAdded(int displayId) {
    }

    @Override
    public void onDisplayChanged(int displayId) {
      refreshRotation();
    }

    @Override
    public void onDisplayRemoved(int displayId) {
    }
  };

  protected void refreshRotation() {
    if (ZoomVideoSDK.getInstance() == null ||
      !ZoomVideoSDK.getInstance().isInSession() ||
      ZoomVideoSDK.getInstance().getVideoHelper() == null) {
      return;
    }

    int displayRotation = display.getRotation();
    if (currentRotation != displayRotation) {
      ZoomVideoSDK.getInstance().getVideoHelper().rotateMyVideo(displayRotation);
      currentRotation = displayRotation;
    }
  }
}
