import TypedEnum from './typed-enum.js';
import '../../utils/types/array.js';
import { fmtIterable } from '../../utils/types/iterable.js';
import 'crypto';
import { maybeNew } from '../../utils/interfaces.js';
import { isEqualToOrPrototypeOf } from '../../utils/inheritance.js';
import 'bs58';
import 'multiformats/bases/base58';
import 'varint';
import '../../utils/encoding/ss-58.js';
import './with-base.js';
import '../../utils/types/bytes.js';
import '../../utils/types/string.js';
import '../../utils/assert.js';
import '../../utils/error.js';
import '../../utils/types/object.js';
import '../../utils/types/set.js';
import './with-catch-null.js';
import './with-eq.js';
import './any-of.js';
import './with-from.js';
import 'blake2b';
import './with-from-json-bytes.js';
import './typed-null.js';
import './create-placeholder.js';

/**
 * 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 (!isEqualToOrPrototypeOf(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: ${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 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];
}

export { withNullIfNotAVariant as default };
//# sourceMappingURL=with-null-if-not-a-variant.js.map
