///|
pub(all) type Many[A] FixedArray[A]

///|
pub impl[A : Show] Show for Many[A] with output(self, logger) {
  if self.inner().length() == 0 {
    logger.write_string("Many([])")
  } else {
    logger.write_string("Many([")
    for i in 0.. Many[A] {
  FixedArray::make(len, init)
}

///|
pub fn[A] Many::from_array(array : Array[A]) -> Many[A] {
  FixedArray::from_array(array)
}

///|
pub fn[A] Many::iter(self : Many[A]) -> Iter[A] {
  self.inner().iter()
}

///|
pub fn[A : Eq] Many::contains(self : Many[A], val : A) -> Bool {
  self.inner().contains(val)
}

///|
pub fn[A : Eq] Many::not_contains(self : Many[A], val : A) -> Bool {
  not(self.contains(val))
}

///|
pub fn[A, B] Many::fold(self : Many[A], init~ : B, f : (B, A) -> B) -> B {
  self.inner().fold(init~, f)
}

///|
pub fn[A, B] Many::foldi(self : Many[A], init~ : B, f : (Int, B, A) -> B) -> B {
  self.inner().foldi(init~, f)
}

///|
pub fn[A] Many::contains_ref(self : Many[A], val : A) -> Bool {
  for a in self.inner() {
    if check_is(a, val) {
      return true
    }
  } else {
    false
  }
}

///|
test "contains_ref" {
  let a : Many[Int] = [1]
  inspect(check_is(a[0], 1), content="true")
}

///|
pub fn[A] Many::not_contains_ref(self : Many[A], val : A) -> Bool {
  not(self.contains_ref(val))
}

///|
pub fn[A] Many::to_array(self : Many[A]) -> Array[A] {
  self.inner() |> Array::from_fixed_array
}

///|
pub fn[I : Show] Many::to_show_array(self : Many[I]) -> Array[&Show] {
  self.inner().map(constant_as_show) |> Array::from_fixed_array
}

///|
pub fn[I : Show] Many::to_show(self : Many[I]) -> Many[&Show] {
  self.inner().map(constant_as_show)
}

///|
pub fn[A] Many::to_fixed_array(self : Many[A]) -> FixedArray[A] {
  self.inner()
}

///|
pub impl[A] Default for Many[A] with default() {
  []
}

///|
pub fn[A] Many::op_get(self : Many[A], i : Int) -> A {
  self.inner()[i]
}

///|
pub fn[A] Many::op_set(self : Many[A], i : Int, v : A) -> Unit {
  self.inner()[i] = v
}

///|
pub fn[A] Many::op_as_view(self : Many[A], start~ : Int, end? : Int) -> Many[A] {
  let end = end.or(self.length())
  Many(FixedArray::makei(end - start, fn(i) { self.inner()[start + i] }))
}

///|
pub impl[A] Slice for Many[A] with op_as_view(self, start~, end~) {
  self.inner() |> Slice::op_as_view(start~, end~) // [start:end]
}

///|
pub impl[A] Length for Many[A] with length(self) {
  self.inner().length()
}