'use strict';

var utils_inheritance = require('../../utils/inheritance.cjs');
var utils_interfaces = require('../../utils/interfaces.cjs');
var types_generic_withBase = require('./with-base.cjs');
var types_generic_withCatchNull = require('./with-catch-null.cjs');
var types_generic_withEq = require('./with-eq.cjs');
require('../../utils/types/object.cjs');
require('../../utils/types/iterable.cjs');
require('../../utils/types/set.cjs');
require('../../utils/assert.cjs');
require('../../utils/error.cjs');
require('../../utils/types/array.cjs');
require('../../utils/types/bytes.cjs');
require('crypto');
require('../../utils/types/string.cjs');
require('bs58');
require('multiformats/bases/base58');
require('varint');
require('../../utils/encoding/ss-58.cjs');
require('blake2b');
require('./with-from-json-bytes.cjs');
require('./any-of.cjs');
require('./with-from.cjs');

let TypedStruct$1 = class TypedStruct extends types_generic_withBase(class StructBase {}) {
  static Classes;

  constructor(...values) {
    super();

    let idx = 0;
    for (const key of Object.keys(this.constructor.Classes)) {
      const prop = Symbol(key);

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

            throw error;
          }
        },
      });

      this[key] = values[idx++];
    }

    utils_inheritance.validateProperties(this);
    Object.seal(this);
  }

  apply(fn) {
    return Object.fromEntries(
      Object.entries(this).map(([key, value]) => [key, fn(value)]),
    );
  }

  static fromJSON(obj) {
    return new this(...Object.keys(this.Classes).map((key) => obj[key]));
  }

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

  eq(other) {
    const thisEntries = Object.entries(this);
    const otherEntries = Object.entries(other);

    if (thisEntries.length !== otherEntries.length) {
      return false;
    }

    for (const key of Object.keys(this)) {
      if (!utils_interfaces.maybeEq(this[key], other[key])) {
        return false;
      }
    }

    return true;
  }

  toString() {
    return JSON.stringify(this.toJSON());
  }

  toJSON() {
    const result = {};
    for (const key of Object.keys(this)) {
      const value = this[key];
      result[key] = value && typeof value.toJSON === 'function' ? value.toJSON() : value;
    }
    return result;
  }
};

var TypedStruct = types_generic_withEq(
  types_generic_withCatchNull(utils_inheritance.withExtendedStaticProperties(['Classes'], TypedStruct$1)),
);

module.exports = TypedStruct;
//# sourceMappingURL=typed-struct.cjs.map
