package com.castlabs.reactnative;

import android.os.Build;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;

import com.castlabs.reactnative.arch_legacy.PlayerViewManager;
import com.castlabs.reactnative.network.NetworkModule;
import com.castlabs.reactnative.network.RequestCompleter;
import com.castlabs.reactnative.network.ResponseCompleter;
import com.castlabs.reactnative.player.Player;
import com.castlabs.reactnative.player.PlayerEventEmitter;
import com.castlabs.reactnative.player.PlayerModule;
import com.castlabs.reactnative.playerview.PlayerView;
import com.castlabs.reactnative.sdk.Plugin;
import com.castlabs.reactnative.sdk.SDKModule;
import com.facebook.react.BaseReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.module.model.ReactModuleInfo;
import com.facebook.react.module.model.ReactModuleInfoProvider;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Bundles media views and modules.
 */
@RequiresApi(api = Build.VERSION_CODES.N)
public class PrestoPlayPackage extends BaseReactPackage {
  public static final Map<String, Player> playerInstanceManager = Collections.synchronizedMap(new HashMap<String, Player>());
  public static final Map<String, PlayerView> playerViewInstanceManager = Collections.synchronizedMap(new HashMap<String, PlayerView>());
  public static final List<Plugin> pluginInstanceManager = Collections.synchronizedList(new ArrayList<Plugin>());

  public static final Map<String, RequestCompleter> requestCompleterCache = Collections.synchronizedMap(new HashMap<String, RequestCompleter>());
  public static final Map<String, ResponseCompleter> responseCompleterCache = Collections.synchronizedMap(new HashMap<String, ResponseCompleter>());

  @NonNull
  @Override
  public List<ViewManager> createViewManagers(
      @NonNull ReactApplicationContext context
  ) {
    return new ArrayList<>(List.of(
        new PlayerViewManager(
            context,
            playerInstanceManager,
            playerViewInstanceManager
        )
    ));
  }

  @Nullable
  @Override
  public NativeModule getModule(@NonNull String name, @NonNull ReactApplicationContext reactApplicationContext) {
    /**
     * Bridge (old) architecture
     */
    if (name.equals(PlayerModule.REACT_CLASS)) {

      PlayerEventEmitter eventEmitter = new PlayerEventEmitter((event) -> {
        reactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                .emit("PrestoPlayEvent", event);
      });
      return new PlayerModule(
              reactApplicationContext,
              playerInstanceManager,
              playerViewInstanceManager,
              pluginInstanceManager,
              requestCompleterCache,
              responseCompleterCache,
              eventEmitter);
    } else if (name.equals(NetworkModule.REACT_CLASS)) {
      return new NetworkModule(
              reactApplicationContext,
              requestCompleterCache,
              responseCompleterCache);
    } else if (name.equals(SDKModule.REACT_CLASS)) {
      return new SDKModule(
              pluginInstanceManager,
              reactApplicationContext);
    }

    return null;
  }

  @NonNull
  @Override
  public ReactModuleInfoProvider getReactModuleInfoProvider() {
    return new ReactModuleInfoProvider() {
      @Override
      public Map<String, ReactModuleInfo> getReactModuleInfos() {
        Map<String, ReactModuleInfo> map = new HashMap<>();

        map.put(PlayerModule.REACT_CLASS, new ReactModuleInfo(
                PlayerModule.REACT_CLASS,       // name
                PlayerModule.REACT_CLASS,       // className
                false, // canOverrideExistingModule
                false, // needsEagerInit
                false, // isCXXModule
                false   // isTurboModule
        ));

        map.put(NetworkModule.REACT_CLASS, new ReactModuleInfo(
                NetworkModule.REACT_CLASS,       // name
                NetworkModule.REACT_CLASS,       // className
                false, // canOverrideExistingModule
                false, // needsEagerInit
                false, // isCXXModule
                false   // isTurboModule
        ));

        map.put(SDKModule.REACT_CLASS, new ReactModuleInfo(
                SDKModule.REACT_CLASS,       // name
                SDKModule.REACT_CLASS,       // className
                false, // canOverrideExistingModule
                false, // needsEagerInit
                false, // isCXXModule
                false   // isTurboModule
        ));

        return map;
      }
    };
  }
}
