import { withExtendedStaticProperties } from '../../utils/inheritance.js';
import { maybeFrom, maybeEq } from '../../utils/interfaces.js';
import { ArrayWithoutPrototypeMethods, ensureArrayLike } from '../../utils/types/array.js';
import 'crypto';
import 'bs58';
import 'multiformats/bases/base58';
import 'varint';
import '../../utils/encoding/ss-58.js';
import withBase from './with-base.js';
import withCatchNull from './with-catch-null.js';
import withEq from './with-eq.js';
import '../../utils/types/object.js';
import '../../utils/types/iterable.js';
import '../../utils/types/set.js';
import '../../utils/assert.js';
import '../../utils/error.js';
import 'blake2b';
import '../../utils/types/bytes.js';
import '../../utils/types/string.js';
import './with-from-json-bytes.js';
import './any-of.js';
import './with-from.js';

class TypedTuple extends withBase(ArrayWithoutPrototypeMethods) {
  /**
   * Item's classes.
   * @type {Array<Function>}
   */
  static Classes;

  static get Size() {
    return this.Classes.length;
  }

  constructor(...items) {
    super(items.length);

    const { Size } = this.constructor;

    if (this.constructor.Size !== items.length) {
      throw new Error(
        `Received \`${items.length}\` items while expected \`${Size}\` by \`${this.constructor.name}\``,
      );
    }

    for (let idx = 0; idx < items.length; idx++) {
      const prop = Symbol(idx);

      Object.defineProperty(this, idx, {
        enumerable: true,
        get() {
          return this[prop];
        },
        set(newValue) {
          try {
            this[prop] = maybeFrom(this.constructor.Classes[idx], newValue);
          } catch (error) {
            error.message = `\nFailed to set property \`${idx}\` of \`${this.constructor.name}\`: ${error.message}`;

            throw error;
          }
        },
      });

      this[idx] = items[idx];
    }

    Object.seal(this);
  }

  apply(fn) {
    return [...this].map(fn);
  }

  static from(value) {
    if (value instanceof this) {
      return value;
    } else if (Array.isArray(value)) {
      return this.fromJSON(value);
    } else if (typeof value === 'object') {
      return this.fromApi(value);
    } else {
      return new this(value);
    }
  }

  static fromJSON(arr) {
    return new this(...ensureArrayLike(arr, this.name));
  }

  static fromApi(arr) {
    return this.fromJSON(arr);
  }

  eq(other) {
    if (this.length !== other.length) {
      return false;
    }

    for (let i = 0; i < this.length; i++) {
      if (!maybeEq(this[i], other[i])) {
        return false;
      }
    }

    return true;
  }
}

var TypedTuple$1 = withEq(
  withCatchNull(withExtendedStaticProperties(['Classes'], TypedTuple)),
);

export { TypedTuple$1 as default };
//# sourceMappingURL=typed-tuple.js.map
