'use strict';

var b58 = require('bs58');
var utils_types_bytes = require('../../../utils/types/bytes.cjs');
var utils_inheritance = require('../../../utils/inheritance.cjs');
require('crypto');
require('../../../utils/interfaces.cjs');
require('../../../utils/assert.cjs');
require('../../../utils/error.cjs');
require('../../../utils/types/string.cjs');
require('../../../utils/types/iterable.cjs');
require('../../../utils/types/object.cjs');
require('../../../utils/types/set.cjs');

function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }

var b58__default = /*#__PURE__*/_interopDefault(b58);

/**
 * Defines commons for the `@docknetwork/crypto-wasm-ts` keypairs.
 */
var DockCryptoKeyPair = utils_inheritance.withExtendedStaticProperties(
  [
    'KeyPair',
    'PublicKey',
    'SecretKey',
    'SignatureParams',
    'Signature',
    'defaultLabelBytes',
  ],
  class DockCryptoKeyPair {
    constructor(options, type) {
      this.type = type;
      this.id = options.id;
      this.controller = options.controller;

      const { keypair } = options;

      if (keypair) {
        this.privateKeyBuffer = keypair.sk.value;
        this.publicKeyBuffer = keypair.pk.value;
      } else {
        this.privateKeyBuffer = options.privateKeyBase58
          ? b58__default.default.decode(options.privateKeyBase58)
          : undefined;
        this.publicKeyBuffer = b58__default.default.decode(String(options.publicKeyBase58));
      }
    }

    static async from(options) {
      return new this(options);
    }

    static get paramGenerator() {
      return this.SignatureParams.getSigParamsOfRequiredSize;
    }

    /**
     * Generates new keypair using provided options.
     *
     * @param options
     * @param options.seed
     * @param options.params
     * @param options.controller
     * @param options.id
     * @param options.msgCount
     */
    static generate({
      seed, params, controller, id, msgCount = 1,
    } = {}) {
      const keypair = this.KeyPair.generate(
        params || this.paramGenerator(msgCount, this.defaultLabelBytes),
        seed,
      );
      return new this({ keypair, controller, id });
    }

    /**
     * Generate object with `sign` method
     * @param keypair
     * @returns {object}
     */
    static signerFactory(key) {
      if (!key.id) {
        return {
          async sign() {
            throw new Error('No key ID for the label.');
          },
        };
      }
      if (!key.privateKeyBuffer) {
        return {
          async sign() {
            throw new Error('No private key to sign with.');
          },
        };
      }
      const { SecretKey, Signature, defaultLabelBytes } = this;
      const keypairClass = this;

      return {
        async sign({ data }) {
          const msgCount = data.length;
          const sigParams = keypairClass.paramGenerator(
            msgCount,
            defaultLabelBytes,
          );
          const sk = keypairClass.adaptKey(
            new SecretKey(utils_types_bytes.u8aToU8a(key.privateKeyBuffer)),
            data.length,
          );
          const signature = Signature.generate(data, sk, sigParams, false);
          return signature.value;
        },
      };
    }

    /**
     * Generate object with `verify` method
     * @param keypair
     * @returns {object}
     */
    static verifierFactory(keypair) {
      if (!keypair.id) {
        return {
          async sign() {
            throw new Error('No key ID for the label.');
          },
        };
      }
      if (!keypair.publicKeyBuffer) {
        return {
          async verify() {
            throw new Error('No public key to verify with.');
          },
        };
      }

      const { PublicKey, Signature, defaultLabelBytes } = this;
      const keypairClass = this;

      return {
        async verify({ data, signature: rawSignature }) {
          const msgCount = data.length;
          const sigParams = keypairClass.paramGenerator(
            msgCount,
            defaultLabelBytes,
          );
          const signature = new Signature(utils_types_bytes.u8aToU8a(rawSignature));

          try {
            const pk = keypairClass.adaptKey(
              new PublicKey(utils_types_bytes.u8aToU8a(keypair.publicKeyBuffer)),
              data.length,
            );
            const result = signature.verify(data, pk, sigParams, false);
            return result.verified;
          } catch (e) {
            console.error('crypto-wasm-ts error:', e);
            return false;
          }
        },
      };
    }

    /**
     * Adapts the provided public or secret key for the given message count.
     * @param {*} key
     * @param {*} _msgCount
     */
    static adaptKey(key, _msgCount) {
      return key;
    }

    /**
     * Returns a signer object for use with jsonld-signatures.
     *
     * @returns {{sign: Function}} A signer for the json-ld block.
     */
    signer() {
      return this.constructor.signerFactory(this);
    }

    /**
     * Returns a verifier object for use with jsonld-signatures.
     *
     * @returns {{verify: Function}} Used to verify jsonld-signatures.
     */
    verifier() {
      return this.constructor.verifierFactory(this);
    }
  },
);

module.exports = DockCryptoKeyPair;
//# sourceMappingURL=DockCryptoKeyPair.cjs.map
