"use strict"
var __createBinding =
  (this && this.__createBinding) ||
  (Object.create
    ? function (o, m, k, k2) {
        if (k2 === undefined) k2 = k
        Object.defineProperty(o, k2, {
          enumerable: true,
          get: function () {
            return m[k]
          }
        })
      }
    : function (o, m, k, k2) {
        if (k2 === undefined) k2 = k
        o[k2] = m[k]
      })
var __setModuleDefault =
  (this && this.__setModuleDefault) ||
  (Object.create
    ? function (o, v) {
        Object.defineProperty(o, "default", { enumerable: true, value: v })
      }
    : function (o, v) {
        o["default"] = v
      })
var __importStar =
  (this && this.__importStar) ||
  function (mod) {
    if (mod && mod.__esModule) return mod
    var result = {}
    if (mod != null)
      for (var k in mod)
        if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k))
          __createBinding(result, mod, k)
    __setModuleDefault(result, mod)
    return result
  }
Object.defineProperty(exports, "__esModule", { value: true })
exports.createComparator = void 0
const tracing_1 = __importStar(require("../../Tracing"))
const fileName_1 = "(@effect-ts/system): _src/Structural/HasEquals/comparator.ts"
const utils_1 = require("./utils")
const { isArray } = Array
const HAS_MAP_SUPPORT = typeof Map === "function"
const HAS_SET_SUPPORT = typeof Set === "function"
const OBJECT_TYPEOF = "object"
function createComparator(createIsEqual) {
  const isEqual =
    typeof createIsEqual === "function" ? createIsEqual(comparator) : comparator
  /**
   * @function comparator
   *
   * @description
   * compare the value of the two objects and return true if they are equivalent in values
   *
   * @param a the value to test against
   * @param b the value to test
   * @param [meta] an optional meta object that is passed through to all equality test calls
   * @returns are a and b equivalent in value
   */
  function comparator(a, b, meta) {
    if ((0, utils_1.sameValueZeroEqual)(a, b)) {
      return true
    }
    if (a && b && typeof a === OBJECT_TYPEOF && typeof b === OBJECT_TYPEOF) {
      if ((0, utils_1.isPlainObject)(a) && (0, utils_1.isPlainObject)(b)) {
        return (0, utils_1.areObjectsEqual)(a, b, isEqual, meta)
      }
      const arrayA = isArray(a)
      const arrayB = isArray(b)
      if (arrayA || arrayB) {
        return arrayA === arrayB && (0, utils_1.areArraysEqual)(a, b, isEqual, meta)
      }
      const aDate = a instanceof Date
      const bDate = b instanceof Date
      if (aDate || bDate) {
        return (
          aDate === bDate && (0, utils_1.sameValueZeroEqual)(a.getTime(), b.getTime())
        )
      }
      const aRegExp = a instanceof RegExp
      const bRegExp = b instanceof RegExp
      if (aRegExp || bRegExp) {
        return aRegExp === bRegExp && (0, utils_1.areRegExpsEqual)(a, b)
      }
      if ((0, utils_1.isPromiseLike)(a) || (0, utils_1.isPromiseLike)(b)) {
        return a === b
      }
      if (HAS_MAP_SUPPORT) {
        const aMap = a instanceof Map
        const bMap = b instanceof Map
        if (aMap || bMap) {
          return aMap === bMap && (0, utils_1.areMapsEqual)(a, b, isEqual, meta)
        }
      }
      if (HAS_SET_SUPPORT) {
        const aSet = a instanceof Set
        const bSet = b instanceof Set
        if (aSet || bSet) {
          return aSet === bSet && (0, utils_1.areSetsEqual)(a, b, isEqual, meta)
        }
      }
      return (0, utils_1.areObjectsEqual)(a, b, isEqual, meta)
    }
    return false
  }
  return isEqual
}
exports.createComparator = createComparator
//# sourceMappingURL=comparator.js.map
