import '../@ember/debug/index.js';
import { peekMeta } from '../@ember/-internals/meta/lib/meta.js';
import { k as sendEvent, n as notifyPropertyChange, E as addListener, F as removeListener } from './cache-DtDz7X5V.js';
import { isDevelopingApp } from '@embroider/macros';
import { assert } from '../@ember/debug/lib/assert.js';

function arrayContentWillChange(array, startIdx, removeAmt, addAmt) {
  // if no args are passed assume everything changes
  if (startIdx === undefined) {
    startIdx = 0;
    removeAmt = addAmt = -1;
  } else {
    if (removeAmt === undefined) {
      removeAmt = -1;
    }
    if (addAmt === undefined) {
      addAmt = -1;
    }
  }
  sendEvent(array, '@array:before', [array, startIdx, removeAmt, addAmt]);
  return array;
}
function arrayContentDidChange(array, startIdx, removeAmt, addAmt, notify = true) {
  // if no args are passed assume everything changes
  if (startIdx === undefined) {
    startIdx = 0;
    removeAmt = addAmt = -1;
  } else {
    if (removeAmt === undefined) {
      removeAmt = -1;
    }
    if (addAmt === undefined) {
      addAmt = -1;
    }
  }
  let meta = peekMeta(array);
  if (notify) {
    if (addAmt < 0 || removeAmt < 0 || addAmt - removeAmt !== 0) {
      notifyPropertyChange(array, 'length', meta);
    }
    notifyPropertyChange(array, '[]', meta);
  }
  sendEvent(array, '@array:change', [array, startIdx, removeAmt, addAmt]);
  if (meta !== null) {
    let length = array.length;
    let addedAmount = addAmt === -1 ? 0 : addAmt;
    let removedAmount = removeAmt === -1 ? 0 : removeAmt;
    let delta = addedAmount - removedAmount;
    let previousLength = length - delta;
    let normalStartIdx = startIdx < 0 ? previousLength + startIdx : startIdx;
    if (meta.revisionFor('firstObject') !== undefined && normalStartIdx === 0) {
      notifyPropertyChange(array, 'firstObject', meta);
    }
    if (meta.revisionFor('lastObject') !== undefined) {
      let previousLastIndex = previousLength - 1;
      let lastAffectedIndex = normalStartIdx + removedAmount;
      if (previousLastIndex < lastAffectedIndex) {
        notifyPropertyChange(array, 'lastObject', meta);
      }
    }
  }
  return array;
}

const EMPTY_ARRAY = Object.freeze([]);

// Ideally, we'd use MutableArray.detect but for unknown reasons this causes
// the node tests to fail strangely.
function isMutableArray(obj) {
  return obj != null && typeof obj.replace === 'function';
}
function replace(array, start, deleteCount, items = EMPTY_ARRAY) {
  if (isMutableArray(array)) {
    array.replace(start, deleteCount, items);
  } else {
    (isDevelopingApp() && !(Array.isArray(array)) && assert('Can only replace content of a native array or MutableArray', Array.isArray(array)));
    replaceInNativeArray(array, start, deleteCount, items);
  }
}
const CHUNK_SIZE = 60000;

// To avoid overflowing the stack, we splice up to CHUNK_SIZE items at a time.
// See https://code.google.com/p/chromium/issues/detail?id=56588 for more details.
function replaceInNativeArray(array, start, deleteCount, items) {
  arrayContentWillChange(array, start, deleteCount, items.length);
  if (items.length <= CHUNK_SIZE) {
    array.splice(start, deleteCount, ...items);
  } else {
    array.splice(start, deleteCount);
    for (let i = 0; i < items.length; i += CHUNK_SIZE) {
      let chunk = items.slice(i, i + CHUNK_SIZE);
      array.splice(start + i, 0, ...chunk);
    }
  }
  arrayContentDidChange(array, start, deleteCount, items.length);
}
function arrayObserversHelper(obj, target, opts, operation) {
  let {
    willChange,
    didChange
  } = opts;
  operation(obj, '@array:before', target, willChange);
  operation(obj, '@array:change', target, didChange);

  /*
   * Array proxies have a `_revalidate` method which must be called to set
   * up their internal array observation systems.
   */
  obj._revalidate?.();
  return obj;
}
function addArrayObserver(array, target, opts) {
  return arrayObserversHelper(array, target, opts, addListener);
}
function removeArrayObserver(array, target, opts) {
  return arrayObserversHelper(array, target, opts, removeListener);
}

export { replace as a, arrayContentWillChange as b, arrayContentDidChange as c, addArrayObserver as d, removeArrayObserver as e, replaceInNativeArray as r };
