package com.reactnativezoom.videosdk;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.WritableNativeArray;

import java.util.List;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import us.zoom.sdk.ZoomVideoSDK;
import com.reactnativezoom.videosdk.convert.RNZoomVideoSdkShareAction;
import com.reactnativezoom.videosdk.convert.RNZoomVideoSDKErrors;

import us.zoom.sdk.SubSessionKit;
import us.zoom.sdk.ZoomVideoSDKSubSessionManager;
import us.zoom.sdk.ZoomVideoSDKSubSessionParticipant;
import us.zoom.sdk.SubSessionUserHelpRequestHandler;
import us.zoom.sdk.SubSessionUser;
import us.zoom.sdk.ZoomVideoSDKSubSessionHelper;

public class RNZoomVideoSdkSubSessionModule extends ReactContextBaseJavaModule {

  private final ReactApplicationContext reactContext;
  private static Map<String, SubSessionKit> subSessionMap = new HashMap<>();
  private static ZoomVideoSDKSubSessionManager subSessionManager;
  private static ZoomVideoSDKSubSessionParticipant subSessionParticipant;
  private static SubSessionUserHelpRequestHandler subSessionUserHelpRequestHandler;

  RNZoomVideoSdkSubSessionModule(ReactApplicationContext reactContext) {
    super(reactContext);
    this.reactContext = reactContext;

  }

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

  public static ReadableMap mapSubSessionKit(SubSessionKit subSession) {
    WritableMap mappedUser = Arguments.createMap();
    mappedUser.putString("subSessionName", subSession.getSubSessionName());
    mappedUser.putString("subSessionID", subSession.getSubSessionID());

    List<SubSessionUser> subSessionUserList = subSession.getSubSessionUserList();
    WritableArray mappedUserArray = new WritableNativeArray();
    for (SubSessionUser user : subSessionUserList) {
      mappedUserArray.pushMap(mapSubSessionUser(user));
    }
    mappedUser.putArray("subSessionUserList", mappedUserArray);

    subSessionMap.put(subSession.getSubSessionID(), subSession);

    return mappedUser;
  }

  public static ReadableArray mapSubSessionKitArray(List<SubSessionKit> kitList) {
    WritableArray mappedArray = new WritableNativeArray();
    for (SubSessionKit kit : kitList) {
      mappedArray.pushMap(mapSubSessionKit(kit));
    }
    return mappedArray;
  }

  public static void updateSubSessionKit(SubSessionKit subSessionKit) {
    subSessionMap.put(subSessionKit.getSubSessionID(), subSessionKit);
  }

  public static ReadableMap mapSubSessionUser(SubSessionUser user) {
    WritableMap mappedUser = Arguments.createMap();
    mappedUser.putString("userName", user.getUserName());
    mappedUser.putString("userGUID", user.getUserGUID());
    return mappedUser;
  }

  public static void storeSubSessionManager(ZoomVideoSDKSubSessionManager manager) {
    RNZoomVideoSdkSubSessionModule.subSessionManager = manager;
  }

  public static void storeSubSessionParticipant(ZoomVideoSDKSubSessionParticipant participant) {
    RNZoomVideoSdkSubSessionModule.subSessionParticipant = participant;
  }

  public static void storeSubSessionUserHelpRequestHandler(SubSessionUserHelpRequestHandler handler) {
    RNZoomVideoSdkSubSessionModule.subSessionUserHelpRequestHandler = handler;
  }

  @ReactMethod
  public void joinSubSession(String subSessionID, Promise promise) {
    if (subSessionMap.get(subSessionID) != null) {
      reactContext.getCurrentActivity().runOnUiThread(new Runnable() {
        @Override
        public void run() {
          promise.resolve(RNZoomVideoSDKErrors.valueOf(subSessionMap.get(subSessionID).joinSubSession()));
        }
      });
    } else {
      promise.reject("join_subsession_failed", "subSessionKit is null", (WritableMap) null);
    }
  }

  @ReactMethod
  public void startSubSession(Promise promise) {
    if (subSessionManager != null) {
      reactContext.getCurrentActivity().runOnUiThread(new Runnable() {
        @Override
        public void run() {
          promise.resolve(RNZoomVideoSDKErrors.valueOf(subSessionManager.startSubSession()));
        }
      });
    } else {
      promise.reject("start_subsession_failed", "subSessionManager is null", (WritableMap) null);
    }
  }

  @ReactMethod
  public void stopSubSession(Promise promise) {
    if (subSessionManager != null) {
      reactContext.getCurrentActivity().runOnUiThread(new Runnable() {
        @Override
        public void run() {
          promise.resolve(RNZoomVideoSDKErrors.valueOf(subSessionManager.stopSubSession()));
        }
      });
    } else {
      promise.reject("stop_subsession_failed", "subSessionManager is null", (WritableMap) null);
    }
  }

  @ReactMethod
  public void isSubSessionStarted(Promise promise) {
    if (subSessionManager != null) {
      reactContext.getCurrentActivity().runOnUiThread(new Runnable() {
        @Override
        public void run() {
          promise.resolve(subSessionManager.isSubSessionStarted());
        }
      });
    } else {
      promise.reject("is_subsession_started_failed", "subSessionManager is null", (WritableMap) null);
    }
  }

  @ReactMethod
  public void broadcastMessage(String message, Promise promise) {
    if (subSessionManager != null) {
      reactContext.getCurrentActivity().runOnUiThread(new Runnable() {
        @Override
        public void run() {
          promise.resolve(RNZoomVideoSDKErrors.valueOf(subSessionManager.broadcastMessage(message)));
        }
      });
    } else {
      promise.reject("broadcast_message_failed", "subSessionManager is null", (WritableMap) null);
    }
  }

  @ReactMethod
  public void returnToMainSession(Promise promise) {
    if (subSessionParticipant != null) {
      reactContext.getCurrentActivity().runOnUiThread(new Runnable() {
        @Override
        public void run() {
          promise.resolve(RNZoomVideoSDKErrors.valueOf(subSessionParticipant.returnToMainSession()));
        }
      });
    } else {
      promise.reject("return_to_main_session_failed", "subSessionParticipant is null", (WritableMap) null);
    }
  }

  @ReactMethod
  public void requestForHelp(Promise promise) {
    if (subSessionParticipant != null) {
      reactContext.getCurrentActivity().runOnUiThread(new Runnable() {
        @Override
        public void run() {
          promise.resolve(RNZoomVideoSDKErrors.valueOf(subSessionParticipant.requestForHelp()));
        }
      });
    } else {
      promise.reject("request_for_help_failed", "subSessionParticipant is null", (WritableMap) null);
    }
  }

  @ReactMethod
  public void getRequestUserName(Promise promise) {
    if (subSessionUserHelpRequestHandler != null) {
      reactContext.getCurrentActivity().runOnUiThread(new Runnable() {
        @Override
        public void run() {
          promise.resolve(subSessionUserHelpRequestHandler.getRequestUserName());
        }
      });
    } else {
      promise.reject("get_request_username_failed", "subSessionUserHelpRequestHandler is null", (WritableMap) null);
    }
  }

  @ReactMethod
  public void getRequestSubSessionName(Promise promise) {
    if (subSessionUserHelpRequestHandler != null) {
      reactContext.getCurrentActivity().runOnUiThread(new Runnable() {
        @Override
        public void run() {
          promise.resolve(subSessionUserHelpRequestHandler.getRequestSubSessionName());
        }
      });
    } else {
      promise.reject("get_request_subsession_name_failed", "subSessionUserHelpRequestHandler is null", (WritableMap) null);
    }
  }

  @ReactMethod
  public void ignore(Promise promise) {
    if (subSessionUserHelpRequestHandler != null) {
      reactContext.getCurrentActivity().runOnUiThread(new Runnable() {
        @Override
        public void run() {
          promise.resolve(RNZoomVideoSDKErrors.valueOf(subSessionUserHelpRequestHandler.ignore()));
        }
      });
    } else {
      promise.reject("ignore_request_failed", "subSessionUserHelpRequestHandler is null", (WritableMap) null);
    }
  }

  @ReactMethod
  public void joinSubSessionByUserRequest(Promise promise) {
    if (subSessionUserHelpRequestHandler != null) {
      reactContext.getCurrentActivity().runOnUiThread(new Runnable() {
        @Override
        public void run() {
          promise.resolve(RNZoomVideoSDKErrors.valueOf(subSessionUserHelpRequestHandler.joinSubSessionByUserRequest()));
        }
      });
    } else {
      promise.reject("join_subsession_by_user_request_failed", "subSessionUserHelpRequestHandler is null", (WritableMap) null);
    }
  }

  @ReactMethod
  public void commitSubSessionList(ReadableArray subSessionNameList, Promise promise) {
    List<String> nameList = new ArrayList<>();
    for (int i = 0; i < subSessionNameList.size(); i++) {
      nameList.add(subSessionNameList.getString(i));
    }
    ZoomVideoSDKSubSessionHelper helper = ZoomVideoSDK.getInstance().getSubSessionHelper();
    if (helper == null) {
      promise.reject("SUBSESSION_HELPER_NULL", "SubSession helper is not available");
      return;
    }

    reactContext.getCurrentActivity().runOnUiThread(new Runnable() {
      @Override
      public void run() {
        promise.resolve(RNZoomVideoSDKErrors.valueOf(helper.commitSubSessionList(nameList)));
      }
    });
  }

  @ReactMethod
  public void withdrawSubSessionList(Promise promise) {
    ZoomVideoSDKSubSessionHelper helper = ZoomVideoSDK.getInstance().getSubSessionHelper();
    if (helper == null) {
      promise.reject("SUBSESSION_HELPER_NULL", "SubSession helper is not available");
      return;
    }

    reactContext.getCurrentActivity().runOnUiThread(new Runnable() {
      @Override
      public void run() {
        promise.resolve(RNZoomVideoSDKErrors.valueOf(helper.withdrawSubSessionList()));
      }
    });
  }

  @ReactMethod
  public void getCommittedSubSessionList(Promise promise) {
    ZoomVideoSDKSubSessionHelper helper = ZoomVideoSDK.getInstance().getSubSessionHelper();
    if (helper == null) {
      promise.reject("SUBSESSION_HELPER_NULL", "SubSession helper is not available");
      return;
    }

    List<SubSessionKit> kitList = helper.getCommittedSubSessionList();
    reactContext.getCurrentActivity().runOnUiThread(new Runnable() {
      @Override
      public void run() {
        promise.resolve(mapSubSessionKitArray(kitList));
      }
    });
  }

}
