'use strict';

var types_generic_typedEnum = require('./typed-enum.cjs');
require('../../utils/types/array.cjs');
var utils_types_iterable = require('../../utils/types/iterable.cjs');
require('crypto');
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');
require('./with-base.cjs');
require('../../utils/types/bytes.cjs');
require('../../utils/types/string.cjs');
require('../../utils/assert.cjs');
require('../../utils/error.cjs');
require('../../utils/types/object.cjs');
require('../../utils/types/set.cjs');
require('./with-catch-null.cjs');
require('./with-eq.cjs');
require('./any-of.cjs');
require('./with-from.cjs');
require('blake2b');
require('./with-from-json-bytes.cjs');
require('./typed-null.cjs');
require('./create-placeholder.cjs');

/**
 * Extends supplied class which must be a successor of `TypedEnum` in a way that every of the methods
 * `from`/`fromJSON`/`fromApi` will return `null` if variant of the provided value is not the same as the underlying type.
 *
 * @template C
 * @param {C} klass
 * @returns {C}
 */
/* eslint-disable sonarjs/cognitive-complexity */
function withNullIfNotAVariant(klass) {
  if (!utils_inheritance.isEqualToOrPrototypeOf(types_generic_typedEnum, klass)) {
    throw new Error('Expected  `{klass.name}` to extend `TypedEnum`');
  } else if (klass.Class == null) {
    throw new Error(
      `Expected static \`Class\` property to be present in \`${klass.name}\``,
    );
  }
  const name = `withNullIfNotAVariant(${klass.name})`;

  const classObj = {
    [name]: class extends klass {
      static fromJSON(value) {
        const keys = Object.keys(value);
        if (keys.length !== 1) {
          throw new Error(
            `Expected object with 1 key, received \`${value}\` with keys: ${utils_types_iterable.fmtIterable(
              keys,
            )} by ${this.name}`,
          );
        }
        const [key] = keys;

        if (this.JsonType === key || this.Type === key) {
          return super.from(value);
        }

        return null;
      }

      static fromApi(obj) {
        if (obj[this.isIdentifier]) {
          return utils_interfaces.maybeNew(this, [obj[this.asIdentifier]]);
        } else {
          return null;
        }
      }

      static from(obj) {
        if (obj instanceof this) {
          return obj;
        } else if (typeof obj === 'string' && this.isNullish) {
          return this.fromJSON(obj);
        } else if (Object.getPrototypeOf(obj) === Object.getPrototypeOf({})) {
          return this.fromJSON(obj);
        } else if (obj instanceof this.Class) {
          return new this(this.Class.from(obj));
        }

        return this.fromApi(obj);
      }
    },
  };

  return classObj[name];
}

module.exports = withNullIfNotAVariant;
//# sourceMappingURL=with-null-if-not-a-variant.cjs.map
