import { entries } from 'izuna'
import { Clone } from './clone.js'
import { IndexableIterator } from './iter.js'

/**
 * @param {...any} values
 */
export class Tuple {
  _values
  _length

  get length() {
    return this._length
  }

  constructor(values) {
    if (values.length > 0) {
      this._length = values.length
      values.forEach(this._setEntry.bind(this))
    }

    this._values = values
  }

  _setEntry([key, value], index) {
    if (typeof key !== 'number') {
      Object.defineProperty(this, key, {
        get() {
          return this[index]
        }
      })
    }

    this[index] = value
  }

  static from(values) {
    return Object.freeze(new this(entries(values)))
  }


  toString() {
    return `(${this._values.map(([_, v]) => v.toString())})`
  }

  clone() {
    return this[Clone]()
  }

  [Clone]() {
    return Object.freeze(new this.constructor(this._values))
  }

  [Symbol.iterator]() {
    return new IndexableIterator(this._values.map(([_, v]) => v))
  }
}

export const tuple = Tuple.from