package com.reactnativerangersapplogreactnativeplugin;

import androidx.annotation.NonNull;

import com.facebook.react.ReactRootView;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.modules.core.DeviceEventManagerModule;

import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

@ReactModule(name = RangersAppLogEmitter.NAME)
public class RangersAppLogEmitter extends ReactContextBaseJavaModule {

  public static final String NAME = "RangersAppLogEmitter";

  private static final String pageShowEvent = "RangersAppLogEmitter_onPageShow";
  private static final String pageHideEvent = "RangersAppLogEmitter_onPageHide";
  private static final String pagePickerEvent = "RangersAppLogEmitter_onPagePicker";
  private boolean hasConnect = false;
  private List<Object[]> delayEvents = new LinkedList();

  public RangersAppLogEmitter(ReactApplicationContext reactContext) {
    super(reactContext);
  }

  @NonNull
  @Override
  public String getName() {
    return NAME;
  }

  @ReactMethod
  public void connect() {
    if (!hasConnect) {
      for (Object[] eventInfo : delayEvents) {
        String eventName = (String) eventInfo[0];
        Map params = (Map) eventInfo[1];
        sendEvent(eventName, params);
      }
      delayEvents.clear();
    }
    hasConnect = true;
  }

  private void sendEvent(String eventName, Map params) {
    WritableMap payload = Arguments.createMap();
    Iterator<Map.Entry> it = params.entrySet().iterator();
    while (it.hasNext()) {
      Map.Entry<String, Object> entry = it.next();
      if (entry.getValue() instanceof Number) {
        payload.putInt(entry.getKey(), (int) entry.getValue());
      } else if (entry.getValue() instanceof Boolean) {
        payload.putBoolean(entry.getKey(), (boolean) entry.getValue());
      } else {
        payload.putString(entry.getKey(), entry.getValue().toString());
      }
    }

    getReactApplicationContext()
      .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
      .emit(eventName, payload);
  }

  public void sendPageShowEvent(IReactRootView rootView, HashMap params) {
    HashMap newParams = new HashMap();
    if (params != null) {
      newParams.putAll(params);
    }

    rootView.findRootTag(rootTag -> {
      params.put("rootTag", Integer.valueOf(rootTag));
      params.put("moduleName", rootView.getJSModuleName());
      if (hasConnect) {
        sendEvent(pageShowEvent, params);
      } else {
        delayEvents.add(new Object[]{ pageShowEvent, params });
      }
    });
  }

  public void sendPageHideEvent(IReactRootView rootView, HashMap params) {
    HashMap newParams = new HashMap();
    if (params != null) {
      newParams.putAll(params);
    }

    rootView.findRootTag(rootTag -> {
      newParams.put("rootTag", Integer.valueOf(rootTag));
      newParams.put("moduleName", rootView.getJSModuleName());
      if (hasConnect) {
        sendEvent(pageHideEvent, newParams);
      } else {
        delayEvents.add(new Object[]{ pageHideEvent, newParams });
      }
    });
  }

  public void sendPagePickerEvent(IReactRootView rootView, HashMap params) {
    HashMap newParams = new HashMap();
    if (params != null) {
      newParams.putAll(params);
    }

    rootView.findRootTag(rootTag -> {
      newParams.put("rootTag", Integer.valueOf(rootTag));
      newParams.put("moduleName", rootView.getJSModuleName());
      if (hasConnect) {
        sendEvent(pagePickerEvent, newParams);
      } else {
        delayEvents.add(new Object[]{ pagePickerEvent, newParams });
      }
    });
  }

}
