/* eslint-disable @typescript-eslint/no-use-before-define */
import * as R from "ramda";
import { NativeModules } from "react-native";
import { ANALYTICS_CORE_EVENTS } from "@applicaster/zapp-react-native-utils/analyticsUtils/events";

import { analyticsUtilsLogger } from "./logger";

const { AnalyticsBridge } = NativeModules;

const startTime = {};
const endTime = {};

/**
 * this function will return true if the Analytics Bridge native module is missing. this
 * allows to skip execution and prevent a crash if this happens
 */
function guardAgainstUndefinedBridge() {
  if (!AnalyticsBridge) {
    analyticsUtilsLogger.warning({
      message: "Analytics Bridge is missing - no event will be sent",
    });

    return true;
  }

  return false;
}

/**
 * Post to application for event type and additional params
 *
 * @param eventName Analytic event name
 * @param payload   Additonal parameters that will be passed with event
 */
export function postAnalyticEvent(eventName: string, payload = {}) {
  if (isValidAnalyticsData(eventName, payload)) {
    if (guardAgainstUndefinedBridge()) {
      return;
    }

    AnalyticsBridge.postEvent(eventName, payload);
  }
}

export function providePlugins(plugins, configs, callback) {
  if (guardAgainstUndefinedBridge()) {
    return;
  }

  AnalyticsBridge.setPlugins(plugins, configs, callback);
}

/**
 * Notify application that timed event was started for event type and additional params.
 *
 * @param eventName Analytic event name
 * @param payload   Additonal parameters that will be passed with event
 */
export function startAnalyticsTimedEvent(eventName: string, payload: object) {
  if (isValidAnalyticsData(eventName, payload)) {
    if (guardAgainstUndefinedBridge()) {
      return;
    }

    startTime[eventName] = new Date();
  }
}

/**
 * Notify application that timed event was finished for event type and additional params.
 *
 * @param eventName Analytic event name
 * @param payload   Additonal parameters that will be passed with event
 */
export function endAnalyticsTimedEvent(eventName: string, payload: object) {
  if (isValidAnalyticsData(eventName, payload)) {
    if (guardAgainstUndefinedBridge()) {
      return;
    }

    if (!startTime[eventName]) {
      analyticsUtilsLogger.error({
        message: `Mismatch in start/endAnalyticsTimedEvent ${eventName}`,
      });
    }

    endTime[eventName] = new Date();
    const toSeconds = (ms) => ms / 1000;

    const duration = startTime[eventName]
      ? toSeconds(endTime[eventName] - startTime[eventName])
      : "N/A";

    const updatedPayload = {
      duration,
      ...payload,
    };

    AnalyticsBridge.postEvent(
      ANALYTICS_CORE_EVENTS.TIME_ON_SCREEN,
      updatedPayload
    );

    startTime[eventName] = null;
    endTime[eventName] = null;
  }
}

/**
 * Checks if analytics data to pass wass passsed expected values
 *
 * @param eventName Analytic event name
 * @param payload   Additonal parameters that will be passed with event
 *
 * @returns {boolean} True in case if parameters suitable for manager to send, otherwise false
 */
export function isValidAnalyticsData(eventName: string, payload: any = null) {
  const eventExist = R.is(String, eventName);
  // we allow payload to be null, but we're leveraging here the fact that typeof null === "object"
  const payloadObjectOrNil = typeof payload === "object";

  return eventExist && payloadObjectOrNil;
}
