import jsonld from 'jsonld';
import { JsonWebKey } from '@transmute/json-web-signature';
import documentLoader from './document-loader.js';
import './crypto/Bls12381BBDT16KeyPairDock2024.js';
import Bls12381BBDT16MACDock2024 from './crypto/Bls12381BBDT16MACDock2024.js';
import './crypto/Bls12381BBDT16MACProofDock2024.js';
import './crypto/Bls12381BBSKeyPairDock2023.js';
import Bls12381BBSSignatureDock2022 from './crypto/Bls12381BBSSignatureDock2022.js';
import Bls12381BBSSignatureDock2023 from './crypto/Bls12381BBSSignatureDock2023.js';
import './crypto/Bls12381BBSSignatureProofDock2022.js';
import './crypto/Bls12381BBSSignatureProofDock2023.js';
import './crypto/Bls12381BDDT16KeyPairDock2024.js';
import './crypto/Bls12381BDDT16MACDock2024.js';
import './crypto/Bls12381BDDT16MACProofDock2024.js';
import './crypto/Bls12381G2KeyPairDock2022.js';
import './crypto/Bls12381PSKeyPairDock2023.js';
import Bls12381PSSignatureDock2023 from './crypto/Bls12381PSSignatureDock2023.js';
import './crypto/Bls12381PSSignatureProofDock2023.js';
import EcdsaSecp256k1Signature2019 from './crypto/EcdsaSecp256k1Signature2019.js';
import 'bs58';
import '@juanelas/base64';
import 'crypto';
import { Bls12381BBDT16DockVerKeyName, Bls12381PSDockVerKeyName, Bls12381BBS23DockVerKeyName, Bls12381BBSDockVerKeyName, Ed255192020VerKeyName, Ed25519VerKeyName, EcdsaSecp256k1VerKeyName, Bls12381BBDT16MacDockName } from './crypto/constants.js';
import '../keypairs/keypair-secp256k1.js';
import 'multiformats/bases/base58';
import Ed25519Signature2018 from './crypto/Ed25519Signature2018.js';
import Ed25519Signature2020 from './crypto/Ed25519Signature2020.js';
import '@stablelib/ed25519';
import '../types/public-keys/public-key.js';
import '../types/public-keys/public-key-sr25519-value.js';
import '../types/public-keys/public-key-ed25519-value.js';
import '../types/public-keys/public-key-secp256k1-value.js';
import '../types/public-keys/public-key-x25519-value.js';
import '../types/signatures/signature-value.js';
import '../types/signatures/signature.js';
import '../utils/types/array.js';
import 'varint';
import '../utils/encoding/ss-58.js';
import '../keypairs/dock-keypair.js';
import JsonWebSignature2020 from './crypto/JsonWebSignature2020.js';
import './crypto/common/CustomLinkedDataSignature.js';
import DidKeypair from '../keypairs/did-keypair.js';
import { possibleVerificationMethodRefs } from '../types/did/document/verification-method-ref.js';
import './contexts.js';
import './contexts/vc-examples-v1.js';
import './contexts/security_context.js';
import './contexts/status-list-21.js';
import './contexts/private-status-list-21.js';
import '../utils/json-fetch.js';
import '@docknetwork/crypto-wasm-ts';
import './crypto/common/DockCryptoKeyPair.js';
import '../utils/types/bytes.js';
import '../utils/interfaces.js';
import '../utils/assert.js';
import '../utils/error.js';
import '../utils/types/string.js';
import '../utils/types/iterable.js';
import '../utils/types/object.js';
import '../utils/inheritance.js';
import '../utils/types/set.js';
import '@docknetwork/crypto-wasm-ts/lib/index.js';
import './crypto/common/DockCryptoSignature.js';
import 'jsonld-signatures';
import 'json-stringify-deterministic';
import 'semver/preload.js';
import 'base64url';
import '../types/generic/typed-enum.js';
import '../types/generic/with-base.js';
import '../types/generic/with-catch-null.js';
import '../types/generic/with-eq.js';
import '../types/generic/any-of.js';
import '../types/generic/with-from.js';
import 'blake2b';
import '../types/generic/with-from-json-bytes.js';
import '../types/generic/typed-null.js';
import '../types/generic/create-placeholder.js';
import '../types/generic/typed-bytes.js';
import '../types/generic/typed-string.js';
import '../types/generic/typed-array.js';
import '../types/generic/typed-tuple.js';
import '../types/generic/typed-number.js';
import '../types/generic/typed-set.js';
import '../types/generic/typed-map.js';
import '../types/generic/typed-struct.js';
import 'uuid';
import 'js-sha256';
import '../types/generic/with-qualifier.js';
import '../types/generic/utils.js';
import '../types/generic/typed-bytes-array.js';
import '../types/did/onchain/typed-did/index.js';
import '../types/did/onchain/typed-did/did-method-key/did-method-key-public-key.js';
import '../utils/encoding/base-58-btc.js';
import '../types/generic/sized.js';
import '../utils/types/number.js';
import '../types/did/onchain/constants.js';
import '../types/did/onchain/typed-did/signature.js';
import '../types/did/onchain/typed-did/did-method-key/did-method-key-signature.js';
import '../types/signatures/signature-ed25519-value.js';
import '../types/signatures/signature-secp256k1-value.js';
import '../types/signatures/signature-sr25519-value.js';
import '../types/did/onchain/typed-did/dock-did-value.js';
import '../types/generic/typed-uuid.js';
import '../types/did/onchain/typed-did/cheqd-did.js';
import './jws.js';
import './crypto/common/DockCryptoSignatureProof.js';
import './crypto/EcdsaSecp256k1VerificationKey2019.js';
import '../utils/encoding/multibase.js';
import 'elliptic';
import './crypto/Ed25519VerificationKey2018.js';
import '../keypairs/keypair-ed25519.js';
import './crypto/Ed25519VerificationKey2020.js';
import '../types/did/onchain/did-key.js';
import '../types/offchain-signatures/params/index.js';
import '../types/offchain-signatures/params/value.js';
import '../types/generic/option.js';
import '../types/offchain-signatures/curve-type.js';
import '../types/offchain-signatures/params/id.js';
import '../types/generic/with-from-dock-id.js';
import '../types/offchain-signatures/public-keys/index.js';
import '../types/generic/with-prop.js';
import '../types/generic/with-props.js';
import '../types/offchain-signatures/public-keys/value.js';
import '../types/offchain-signatures/public-keys/ref.js';
import '../types/offchain-signatures/public-keys/id.js';
import '../types/did/onchain/verification-relationship.js';
import '../types/did/document/verification-method-ref-or-ident-ref.js';
import '../types/did/document/ident-ref.js';

/**
 * @typedef {object} KeyDoc The Options to use in the function createUser.
 * @property {string} id The key's ID
 * @property {any} controller The key's controller ste
 * @property {any} type the type of key, Sr25519VerificationKey2020 or Ed25519VerificationKey2018 or EcdsaSecp256k1VerificationKey2019
 * @property {object} keypair Keypair is generated by either using polkadot-js's keyring or utils
 * @property {object} publicKey The key's public key taken from the keypair
 */

/**
 * Helper to get the key doc in a format needed for vc.js.
 * @param {string} did - DID in fully qualified form
 * @param {object} keypair - Keypair is generated by either using polkadot-js's keyring for Sr25519 and
 * Ed25519 or keypair generated with `generateEcdsaSecp256k1Keypair` for curve secp256k1.
 * @param {string} type - the type of key, Sr25519VerificationKey2020 or Ed25519VerificationKey2018 or EcdsaSecp256k1VerificationKey2019 or Bls12381G2VerificationKeyDock2022
 * @param {string} id - the ID of the key for future resolution
 * @returns {KeyDoc}
 */
function getKeyDoc(did, kp, type, id) {
  const keypair = kp instanceof DidKeypair ? kp.keyPair : kp;

  return {
    id: id || `${did}#keys-1`,
    controller: String(did),
    type: type || keypair.constructor.VerKeyType,
    keypair,
  };
}

/**
 * Get signature suite from a keyDoc
 * @param {object} keyDoc - key document containing `id`, `controller`, `type`, `privateKeyBase58` and `publicKeyBase58`
 * @returns {object} - signature suite.
 */
async function getSuiteFromKeyDoc(keyDoc, useProofValue, options) {
  // Check if passing suite directly
  if (keyDoc.verificationMethod) {
    return keyDoc;
  }

  let Cls;
  let { keypair } = keyDoc;
  switch (keyDoc.type) {
    case EcdsaSecp256k1VerKeyName:
      Cls = EcdsaSecp256k1Signature2019;
      break;
    case Ed25519VerKeyName:
      Cls = Ed25519Signature2018;
      break;
    case Ed255192020VerKeyName:
      Cls = Ed25519Signature2020;
      break;
    case Bls12381BBSDockVerKeyName:
      Cls = Bls12381BBSSignatureDock2022;
      break;
    case Bls12381BBS23DockVerKeyName:
      Cls = Bls12381BBSSignatureDock2023;
      break;
    case Bls12381PSDockVerKeyName:
      Cls = Bls12381PSSignatureDock2023;
      break;
    case Bls12381BBDT16DockVerKeyName:
      Cls = Bls12381BBDT16MACDock2024;
      break;
    case 'JsonWebKey2020':
      Cls = JsonWebSignature2020;
      if (!keypair) {
        keypair = await JsonWebKey.from(keyDoc, options);
      }
      break;
    default:
      throw new Error(`Unknown key type ${keyDoc.type}.`);
  }

  return new Cls({
    ...keyDoc,
    verificationMethod: keyDoc.id,
    useProofValue,
    keyDoc,
    keypair,
  });
}

/**
 * Helper method to ensure credential is valid according to the context
 * @param credential
 */
async function expandJSONLD(credential, options = {}) {
  if (options.documentLoader && options.resolver) {
    throw new Error(
      'Passing resolver and documentLoader results in resolver being ignored, please re-factor.',
    );
  }

  const expanded = await jsonld.expand(credential, {
    ...options,
    documentLoader:
      options.documentLoader || documentLoader(options.resolver),
  });
  return expanded[0];
}

function potentialToArray(a) {
  /* eslint-disable no-nested-ternary */
  return a ? (Array.isArray(a) ? a : [a]) : [];
}

/**
 * Compares a verification method reference with a key ID to determine if they are equivalent.
 * The function checks if the reference might start with `did:dock:`, and converts it to a `did:cheqd:` format for comparison.
 *
 * @param {string} ref - The verification method reference to compare.
 * @param {string} keyId - The key ID to compare against.
 * @returns {boolean} - Returns `true` if the references are equivalent, `false` otherwise.
 */
const verMethodRefsEqual = (ref, keyId) => ref === keyId
  || possibleVerificationMethodRefs(ref).some((id) => id === keyId);

function getKeyFromDIDDocument(didDocument, didUrl) {
  // Ensure not already a key doc
  if (
    didDocument.publicKeyBase58
    || didDocument.publicKeyMultibase
    || didDocument.publicKeyJwk
    || (didDocument.publicKey && !Array.isArray(didDocument.publicKey))
  ) {
    return didDocument;
  }

  const possibleKeys = [
    ...potentialToArray(didDocument.verificationMethod),
    ...potentialToArray(didDocument.keyAgreement),
    ...potentialToArray(didDocument.publicKey),
  ];

  return possibleKeys.find((key) => verMethodRefsEqual(didUrl, key.id));
}

/**
 * For KVAC, public key is not present so the holder assumes that the given credential is valid.
 * Secondly, these credentials are never shared as it is with the verifier so this function returns true if the credential is
 * a KVAC, else returns undefined.
 * @param credential
 * @returns {object | undefined}
 */
function processIfKvac(credential) {
  const { proof } = credential;
  if (proof === undefined || proof.type === undefined) {
    throw new Error(
      `Credential should have a non-null type field but found ${proof.type}`,
    );
  }
  if (proof.type === Bls12381BBDT16MacDockName) {
    return {
      results: [
        {
          verified: true,
          proof,
          verificationMethod: {},
          purposeResult: {},
        },
      ],
      verified: true,
    };
  }
  return undefined;
}

export { expandJSONLD, getKeyDoc, getKeyFromDIDDocument, getSuiteFromKeyDoc, potentialToArray, processIfKvac, verMethodRefsEqual };
//# sourceMappingURL=helpers.js.map
