'use strict';

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

/**
 * Enhances provided class by adding prototype methods `toString`/`eq`, static `from` and requiring
 * successor to implement static `fromJSON`/`fromApi` and prototype `toJSON`.
 *
 * @templace C
 * @param {C} klass
 * @returns {C}
 */
function withBase(klass) {
  const name = `withBase(${klass.name})`;

  const classes = {
    [name]: class extends klass {
      /**
       * Attempts to instantiate `this` from the provided JSON object.
       * @param {object} json
       */
      static fromJSON(_json) {
        throw new Error('Unimplemented');
      }

      /**
       * Attempts to instantiate `this` from the provided object received from the API side.
       * @param {object} json
       */
      static fromApi(_obj) {
        throw new Error('Unimplemented');
      }

      /**
       * Instantiates `this` from the supplied object.
       * @param obj
       */
      static from(obj) {
        if (obj instanceof this) {
          return obj;
        } else if (Object.getPrototypeOf(obj) === Object.getPrototypeOf({})) {
          return this.fromJSON(obj);
        } else {
          return this.fromApi(obj);
        }
      }

      /**
       * Converts the instance to a JSON representation.
       * @returns {object} The JSON representation of the instance.
       */
      toJSON() {
        return this.apply(utils_interfaces.maybeToJSON);
      }

      /**
       * Recursively applies supplied function to the underlying values.
       * @template T
       * @param {function(this): T} _fn
       * @returns {T}
       */
      apply(_fn) {
        throw new Error('Unimplemented');
      }

      /**
       * Converts the instance to a stringified JSON representation.
       * @returns {string} The JSON representation of the instance.
       */
      toJSONString() {
        return JSON.stringify(this.toJSON());
      }

      /**
       * Converts the instance to bytes of the stringified JSON representation.
       * @returns {Uint8Array} The JSON representation of the instance.
       */
      toJSONStringBytes() {
        return utils_types_bytes.stringToU8a(this.toJSONString());
      }

      /**
       * Converts the instance to a string representation.
       * @returns {string}
       */
      toString() {
        return JSON.stringify(this.toJSON());
      }

      /**
       * Performs an equality check against other value.
       *
       * @param {*} other
       * @returns {boolean}
       */
      eq(other) {
        return utils_interfaces.maybeEq(this.value, other.value);
      }
    },
  };

  return utils_inheritance.withExtendedStaticProperties(
    ['fromJSON', 'fromApi'],
    utils_inheritance.withExtendedPrototypeProperties(
      ['apply'],
      types_generic_withFromJsonBytes(types_generic_withEq(types_generic_withCatchNull(classes[name]))),
    ),
  );
}

module.exports = withBase;
//# sourceMappingURL=with-base.cjs.map
