import * as R from "ramda";
import { logger } from "@applicaster/zapp-react-native-utils/logger";

const numberUtilsLogger = logger?.addSubsystem("NumberUtils");

export const toNumber = (value: any): number | undefined => {
  if (R.isNil(value) || R.isEmpty(value)) {
    return undefined;
  }

  if (R.is(Number, value) || R.is(String, value)) {
    const numberOrNan = Number(value);

    return Number.isNaN(numberOrNan) ? undefined : numberOrNan;
  }

  return undefined;
};

export const toNumberWithDefault = (defaultValue: number, value: any): number =>
  toNumber(value) ?? defaultValue;

export const toNumberWithDefaultZero = (value: any): number =>
  toNumberWithDefault(0, value);

export const requireNumber = (obj, key: string) => {
  const number = toNumber(obj?.[key]);

  if (!number) {
    numberUtilsLogger.warning(
      `requireNumber: invalid number value for: ${key}`
    );

    return null;
  }

  return number;
};

export const toFiniteNumberWithDefault = (
  defaultValue: number,
  value: any
): number => {
  const possibleNumber = toNumberWithDefault(defaultValue, value);

  if (!Number.isFinite(possibleNumber)) {
    return defaultValue;
  }

  return possibleNumber;
};

export const isLikeNumber = (value: unknown): boolean => {
  const possibleNumber = toNumber(value);

  if (R.isNil(possibleNumber)) {
    return false;
  }

  return true;
};

export const isZero = (value: unknown): boolean =>
  Object.is(value, -0) || Object.is(value, 0);

export const isMinusZero = (value: number) => {
  return 1 / value === -Infinity;
};

export const toPositiveNumberWithDefault = (
  defaultValue: number,
  value: unknown
): number => {
  const possibleNumber = toNumber(value);

  if (R.isNil(possibleNumber)) {
    return defaultValue;
  }

  if (possibleNumber < 0) {
    return defaultValue;
  }

  return possibleNumber;
};

export const toPositiveNumberWithDefaultZero = (value: unknown): number =>
  toPositiveNumberWithDefault(0, value);
