import { signPresentation, verifyPresentation } from './presentations.js';
import { getUniqueElementsFromArray } from '../utils/types/array.js';
import { isObject, ensureObjectWithId } from '../utils/types/object.js';
import { ensureString } from '../utils/types/string.js';
import 'crypto';
import 'bs58';
import 'multiformats/bases/base58';
import 'varint';
import '../utils/encoding/ss-58.js';
import { ensureURI } from '../utils/ident/ensure-ident.js';
import VerifiableCredential from './verifiable-credential.js';
import 'jsonld';
import 'jsonld-signatures';
import '@docknetwork/crypto-wasm-ts';
import '@docknetwork/vc-delegation-engine';
import './credentials.js';
import '@digitalcredentials/vc-status-list';
import 'base64url';
import './CredentialIssuancePurpose.js';
import './helpers.js';
import '@transmute/json-web-signature';
import './document-loader.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 './crypto/Bls12381BBDT16KeyPairDock2024.js';
import './crypto/constants.js';
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/iterable.js';
import '../utils/inheritance.js';
import '../utils/types/set.js';
import './crypto/Bls12381BBDT16MACDock2024.js';
import '@docknetwork/crypto-wasm-ts/lib/index.js';
import './crypto/common/DockCryptoSignature.js';
import 'json-stringify-deterministic';
import 'semver/preload.js';
import './crypto/common/CustomLinkedDataSignature.js';
import '../types/did/document/verification-method-ref.js';
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/public-keys/public-key.js';
import '../types/public-keys/public-key-x25519-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-sr25519-value.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-value.js';
import '../types/signatures/signature-ed25519-value.js';
import '../types/signatures/signature-secp256k1-value.js';
import '../types/signatures/signature.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/Bls12381BBDT16MACProofDock2024.js';
import './crypto/common/DockCryptoSignatureProof.js';
import './crypto/Bls12381BBSKeyPairDock2023.js';
import './crypto/Bls12381BBSSignatureDock2022.js';
import './crypto/Bls12381G2KeyPairDock2022.js';
import './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/Bls12381PSKeyPairDock2023.js';
import './crypto/Bls12381PSSignatureDock2023.js';
import './crypto/Bls12381PSSignatureProofDock2023.js';
import './crypto/EcdsaSecp256k1Signature2019.js';
import './crypto/EcdsaSecp256k1VerificationKey2019.js';
import '@juanelas/base64';
import '../keypairs/keypair-secp256k1.js';
import 'elliptic';
import '../keypairs/dock-keypair.js';
import '../utils/encoding/multibase.js';
import './crypto/Ed25519Signature2018.js';
import './crypto/Ed25519VerificationKey2018.js';
import '../keypairs/keypair-ed25519.js';
import '@stablelib/ed25519';
import './crypto/Ed25519Signature2020.js';
import './crypto/Ed25519VerificationKey2020.js';
import './crypto/JsonWebSignature2020.js';
import '../keypairs/did-keypair.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';
import './schema.js';
import 'jsonschema';
import './constants.js';
import './revocation.js';
import 'blakejs';
import '../utils/ident/matchers.js';

// import DIDResolver from "../resolver/did/did-resolver"; // eslint-disable-line

const DEFAULT_CONTEXT = 'https://www.w3.org/2018/credentials/v1';
const DEFAULT_TYPE = 'VerifiablePresentation';

/**
 * @typedef {object} VerifiablePresentationVerificationResult The presentation verification result
 * @property {object} presentationResult Is this presentqtion verified or not
 * @property {array} credentialResults Verification results
 * @property {Boolean} verified Is verified or not
 * @property {any} [error] Optional error
 */

/**
 * Representation of a Verifiable Presentation.
 */
class VerifiablePresentation {
  /**
   * Create a new Verifiable Presentation instance.
   * @param {string} id - id of the presentation
   * @constructor
   */
  constructor(id) {
    ensureURI(id);
    this.id = id;
    this.context = [DEFAULT_CONTEXT];
    this.type = [DEFAULT_TYPE];
    this.credentials = [];
    this.proof = null;
  }

  static fromJSON(json) {
    const {
      verifiableCredential, id, type, ...rest
    } = json;
    const vp = new VerifiablePresentation(id);

    if (type) {
      vp.type = [];
      if (type.length !== undefined) {
        type.forEach((typeVal) => {
          vp.addType(typeVal);
        });
      } else {
        vp.addType(type);
      }
    } else {
      throw new Error(
        'No type found in JSON object, verifiable presentations must have a type field.',
      );
    }

    const context = rest['@context'];
    if (context) {
      vp.setContext(rest['@context']);
      delete rest['@context'];
    } else {
      throw new Error(
        'No context found in JSON object, verifiable presentations must have a @context field.',
      );
    }

    if (verifiableCredential) {
      if (verifiableCredential.length) {
        verifiableCredential.forEach((credential) => {
          vp.addCredential(credential);
        });
      } else {
        vp.addCredential(verifiableCredential);
      }
    }

    Object.assign(vp, rest);
    return vp;
  }

  /**
   * Sets the context to the given value, overrding all others
   * @param {string|object} context - Context to assign
   * @returns {VerifiablePresentation}
   */
  setContext(context) {
    if (!isObject(context) && !Array.isArray(context)) {
      ensureURI(context);
    }
    this.context = context;
    return this;
  }

  /**
   * Add a context to this Presentation's context array. Duplicates are omitted.
   * @param {string|object} context - Context to add to the presentation context array
   * @returns {VerifiablePresentation}
   */
  addContext(context) {
    if (!isObject(context)) {
      ensureURI(context);
    }
    this.context = getUniqueElementsFromArray(
      [...this.context, context],
      JSON.stringify,
    );
    return this;
  }

  /**
   * Add a type to this Presentation's type array. Duplicates are omitted.
   * @param {string} type - Type to add to the presentation type array
   * @returns {VerifiablePresentation}
   */
  addType(type) {
    ensureString(type);
    this.type = [...new Set([...this.type, type])];
    return this;
  }

  /**
   * Set a holder for this Presentation
   * @param {string} holder - Holder to add to the presentation
   * @returns {VerifiablePresentation}
   */
  setHolder(holder) {
    ensureURI(holder);
    this.holder = holder;
    return this;
  }

  /**
   * Add a Verifiable Credential to this Presentation.
   * @param {object} credential -  Verifiable Credential for the presentation
   * @returns {VerifiablePresentation}
   */
  addCredential(credential) {
    let cred = credential;
    if (credential instanceof VerifiableCredential) {
      cred = credential.toJSON();
    }
    ensureObjectWithId(cred, 'credential');
    this.credentials.push(cred);

    return this;
  }

  /**
   * Add multiple Verifiable Credentials to this Presentation.
   * @param {Array<object>} credentials -  Verifiable Credential for the presentation
   * @returns {VerifiablePresentation}
   */
  addCredentials(credentials) {
    credentials.forEach(this.addCredential.bind(this));
  }

  /**
   * Define the JSON representation of a Verifiable Presentation.
   * @returns {object}
   */
  toJSON() {
    const { context, credentials, ...rest } = this;
    return {
      '@context': context,
      verifiableCredential: credentials,
      ...rest,
    };
  }

  /**
   * Sign a Verifiable Presentation using the provided keyDoc
   * @param {object} keyDoc - document with `id`, `controller`, `type`, `privateKeyBase58` and `publicKeyBase58`
   * @param {string} challenge - proof challenge Required.
   * @param {string} domain - proof domain (optional)
   * @param {DIDResolver} [resolver] - Resolver for DIDs.
   * @param {Boolean} [compactProof] - Whether to compact the JSON-LD or not.
   * @returns {Promise<VerifiablePresentation>}
   */
  async sign(keyDoc, challenge, domain, resolver = null, compactProof = true) {
    const signedVP = await signPresentation(
      this.toJSON(),
      keyDoc,
      challenge,
      domain,
      resolver,
      compactProof,
    );
    this.context = signedVP['@context'];
    this.proof = signedVP.proof;
    return this;
  }

  /**
   * Verify a Verifiable Presentation
   * @param {object} [params] Verify parameters (TODO: add type info for this object)
   * @returns {Promise<VerifiablePresentationVerificationResult>} - verification result.
   */
  async verify({
    challenge,
    domain,
    resolver = null,
    compactProof = true,
    skipRevocationCheck = false,
    skipSchemaCheck = false,
    verifyMatchingIssuersForRevocation = true,
    suite = [],
  } = {}) {
    if (!this.proof) {
      throw new Error('The current VerifiablePresentation has no proof.');
    }

    return verifyPresentation(this.toJSON(), {
      challenge,
      domain,
      resolver,
      compactProof,
      skipRevocationCheck,
      skipSchemaCheck,
      verifyMatchingIssuersForRevocation,
      suite,
    });
  }
}

export { VerifiablePresentation as default };
//# sourceMappingURL=verifiable-presentation.js.map
