"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
  }
var __exportStar =
  (this && this.__exportStar) ||
  function (m, exports) {
    for (var p in m)
      if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p))
        __createBinding(exports, m, p)
  }
Object.defineProperty(exports, "__esModule", { value: true })
exports.ChunkBuilder =
  exports.builder =
  exports.many =
  exports.unit =
  exports.materialize =
  exports.reverse =
  exports.reverseBuckets =
  exports.buckets =
  exports.isEmpty =
  exports.unsafeLast =
  exports.unsafeTail =
  exports.unsafeHead =
  exports.last =
  exports.tail =
  exports.head =
  exports.flatten =
  exports.chain =
  exports.chain_ =
  exports.map =
  exports.map_ =
  exports.size =
  exports.drop =
  exports.drop_ =
  exports.take =
  exports.take_ =
  exports.equals =
  exports.equals_ =
  exports.unsafeGet =
  exports.unsafeGet_ =
  exports.get =
  exports.get_ =
  exports.toArray =
  exports.toArrayLike =
  exports.concat_ =
  exports.concat =
  exports.prepend_ =
  exports.prepend =
  exports.append_ =
  exports.append =
  exports.empty =
  exports.single =
    void 0
const tracing_1 = __importStar(require("../../../Tracing"))
const fileName_1 = "(@effect-ts/system): _src/Collections/Immutable/Chunk/core.ts"
const Function_1 = require("../../../Function")
const GlobalExceptions_1 = require("../../../GlobalExceptions")
const O = __importStar(require("../../../Option"))
const St = __importStar(require("../../../Structural"))
const definition_1 = require("./definition")
__exportStar(require("./definition"), exports)
/**
 * Builds a chunk of a single value
 */
function single(a) {
  return new definition_1.Singleton(a)
}
exports.single = single
/**
 * Builds an empty chunk
 */
function empty() {
  return definition_1._Empty
}
exports.empty = empty
/**
 * Appends a value to a chunk
 *
 * @dataFirst append_
 */
function append(a) {
  return (self) => self.append(a)
}
exports.append = append
/**
 * Appends a value to a chunk
 */
function append_(self, a) {
  return self.append(a)
}
exports.append_ = append_
/**
 * Prepends a value to a chunk
 *
 * @dataFirst prepend_
 */
function prepend(a) {
  return (self) => self.prepend(a)
}
exports.prepend = prepend
/**
 * Prepends a value to a chunk
 */
function prepend_(self, a) {
  return self.prepend(a)
}
exports.prepend_ = prepend_
/**
 * Concats chunks
 *
 * @dataFirst concat_
 */
function concat(that) {
  return (self) => self.concat(that)
}
exports.concat = concat
/**
 * Concats chunks
 */
function concat_(self, that) {
  return self.concat(that)
}
exports.concat_ = concat_
/**
 * Converts a chunk to an ArrayLike (either Array or Buffer)
 */
function toArrayLike(self) {
  return self.arrayLike()
}
exports.toArrayLike = toArrayLike
/**
 * Converts a chunk to an Array
 */
function toArray(self) {
  return self.array()
}
exports.toArray = toArray
/**
 * Safely get a value
 */
function get_(self, n) {
  return !Number.isInteger(n) || n < 0 || n >= self.length
    ? O.none
    : O.some(self.get(n))
}
exports.get_ = get_
/**
 * Safely get a value
 *
 * @dataFirst get_
 */
function get(n) {
  return (self) => get_(self, n)
}
exports.get = get
/**
 * Unsafely get a value
 */
function unsafeGet_(self, n) {
  return self.get(n)
}
exports.unsafeGet_ = unsafeGet_
/**
 * Safely get a value
 *
 * @dataFirst unsafeGet_
 */
function unsafeGet(n) {
  return (self) => unsafeGet_(self, n)
}
exports.unsafeGet = unsafeGet
/**
 * Referential equality check
 */
function equals_(self, that) {
  return (0, definition_1.corresponds_)(self, that, St.equals)
}
exports.equals_ = equals_
/**
 * Referential equality check
 *
 * @dataFirst equals_
 */
function equals(that) {
  return (self) => equals_(self, that)
}
exports.equals = equals
/**
 * Takes the first n elements
 */
function take_(self, n) {
  return self.take(n)
}
exports.take_ = take_
/**
 * Takes the first n elements
 *
 * @dataFirst take_
 */
function take(n) {
  return (self) => self.take(n)
}
exports.take = take
/**
 * Drops the first n elements
 */
function drop_(self, n) {
  if (n <= 0) {
    return self
  } else if (n >= self.length) {
    return definition_1._Empty
  } else {
    const len = self.length
    switch (self._typeId) {
      case definition_1.EmptyTypeId: {
        return definition_1._Empty
      }
      case definition_1.SliceTypeId: {
        return new definition_1.Slice(self.chunk, self.offset + n, self.length - n)
      }
      case definition_1.SingletonTypeId: {
        if (n > 0) {
          return definition_1._Empty
        }
        return self
      }
      default: {
        return new definition_1.Slice(self, n, len - n)
      }
    }
  }
}
exports.drop_ = drop_
/**
 * Drops the first n elements
 *
 * @dataFirst drop_
 */
function drop(n) {
  return (self) => self.take(n)
}
exports.drop = drop
/**
 * Returns the number of elements in the chunk
 */
function size(self) {
  return self.length
}
exports.size = size
/**
 * Returns a chunk with the elements mapped by the specified function.
 */
function map_(self, f) {
  if (self._typeId === definition_1.SingletonTypeId) {
    return new definition_1.Singleton(f(self.a))
  }
  let r = empty()
  for (const k of self) {
    r = append_(r, f(k))
  }
  return r
}
exports.map_ = map_
/**
 * Returns a chunk with the elements mapped by the specified function.
 *
 * @dataFirst map_
 */
function map(f) {
  return (self) => map_(self, f)
}
exports.map = map
/**
 * Returns a chunk with the elements mapped by the specified function.
 */
function chain_(self, f) {
  if (self._typeId === definition_1.SingletonTypeId) {
    return f(self.a)
  }
  let r = empty()
  for (const k of self) {
    r = concat_(r, f(k))
  }
  return r
}
exports.chain_ = chain_
/**
 * Returns a chunk with the elements mapped by the specified function.
 *
 * @dataFirst chain_
 */
function chain(f) {
  return (self) => chain_(self, f)
}
exports.chain = chain
/**
 * Flattens a chunk of chunks into a single chunk by concatenating all chunks.
 */
function flatten(self) {
  return chain_(self, Function_1.identity)
}
exports.flatten = flatten
/**
 * Returns the first element of this chunk if it exists.
 */
function head(self) {
  return get_(self, 0)
}
exports.head = head
/**
 * Returns every elements after the first
 */
function tail(self) {
  return self.length > 0 ? O.some(drop_(self, 1)) : O.none
}
exports.tail = tail
/**
 * Returns the last element of this chunk if it exists.
 */
function last(self) {
  return get_(self, self.length - 1)
}
exports.last = last
/**
 * Returns the first element of this chunk. Note that this method is partial
 * in that it will throw an exception if the chunk is empty. Consider using
 * `head` to explicitly handle the possibility that the chunk is empty
 * or iterating over the elements of the chunk in lower level, performance
 * sensitive code unless you really only need the first element of the chunk.
 */
function unsafeHead(self) {
  return self.get(0)
}
exports.unsafeHead = unsafeHead
/**
 * Returns every elements after the first. Note that this method is partial
 * in that it will throw an exception if the chunk is empty. Consider using
 * `head` to explicitly handle the possibility that the chunk is empty
 * or iterating over the elements of the chunk in lower level, performance
 * sensitive code unless you really only need the first element of the chunk.
 */
function unsafeTail(self) {
  if (self.length === 0) {
    throw new GlobalExceptions_1.ArrayIndexOutOfBoundsException(1)
  }
  return drop_(self, 1)
}
exports.unsafeTail = unsafeTail
/**
 * Returns the last element of this chunk. Note that this method is partial
 * in that it will throw an exception if the chunk is empty. Consider using
 * `last` to explicitly handle the possibility that the chunk is empty
 * or iterating over the elements of the chunk in lower level, performance
 * sensitive code unless you really only need the last element of the chunk.
 */
function unsafeLast(self) {
  return self.get(self.length - 1)
}
exports.unsafeLast = unsafeLast
/**
 * Determines if the chunk is empty.
 */
function isEmpty(self) {
  return self.length === 0
}
exports.isEmpty = isEmpty
/**
 * Buckets iterator
 */
function buckets(self) {
  return self.buckets()
}
exports.buckets = buckets
/**
 * Reverse buckets iterator
 */
function reverseBuckets(self) {
  return self.reverseBuckets()
}
exports.reverseBuckets = reverseBuckets
/**
 * Reverse buckets iterator
 */
function reverse(self) {
  return self.reverse()
}
exports.reverse = reverse
/**
 * Materializes a chunk into a chunk backed by an array. This method can
 * improve the performance of bulk operations.
 */
function materialize(self) {
  return self.materialize()
}
exports.materialize = materialize
/**
 * The unit chunk
 */
exports.unit = single(void 0)
/**
 * Build a chunk from a sequence of values
 *
 * NOTE: different from Chunk#from this copies the elements 1 by 1
 * allowing for binary to be correctly stored in typed arrays
 */
function many(...iter) {
  let builder = empty()
  for (const x of iter) {
    builder = append_(builder, x)
  }
  return builder
}
exports.many = many
/**
 * Builder
 */
function builder() {
  return new ChunkBuilder(empty())
}
exports.builder = builder
class ChunkBuilder {
  constructor(chunk) {
    this.chunk = chunk
  }
  append(a) {
    this.chunk = append_(this.chunk, a)
    return this
  }
  build() {
    return this.chunk
  }
}
exports.ChunkBuilder = ChunkBuilder
//# sourceMappingURL=core.js.map
