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

/**
 * 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(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 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 maybeEq(this.value, other.value);
      }
    },
  };

  return withExtendedStaticProperties(
    ['fromJSON', 'fromApi'],
    withExtendedPrototypeProperties(
      ['apply'],
      withFromJSONBytes(withEq(withCatchNull(classes[name]))),
    ),
  );
}

export { withBase as default };
//# sourceMappingURL=with-base.js.map
