'use strict';

var secp256k1 = require('secp256k1');
var hash_js = require('ethereumjs-util/dist/hash.js');
var minterjsWallet = require('minterjs-wallet');
var minterjsTx = require('minterjs-tx');
var minterjsUtil = require('minterjs-util');
var utils = require('../utils.js');

/**
 * @param {object} txData
 * @param {ByteArray} txData.check
 * @param {ByteArray} [txData.proof]
 * @param {TxOptions} [options]
 * @constructor
 */
function RedeemCheckTxData(_ref) {
  var check = _ref.check,
    proof = _ref.proof;
  var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  if (!options.disableValidation) {
    utils.validateCheck(check, 'check');
  }

  // eslint-disable-next-line prefer-rest-params
  if (!options.password && arguments[0].password) {
    // eslint-disable-next-line prefer-rest-params
    options.password = arguments[0].password;
    // eslint-disable-next-line no-console
    console.warn('Check password in tx data is deprecated. Pass it as field in the second argument.');
  }
  // eslint-disable-next-line prefer-rest-params
  if (!options.privateKey && arguments[0].privateKey) {
    // eslint-disable-next-line prefer-rest-params
    options.privateKey = arguments[0].privateKey;
    // eslint-disable-next-line no-console
    console.warn('Private key in tx data is deprecated. Pass it as field in the second argument.');
  }
  this.check = minterjsUtil.checkToString(check);
  if (proof) {
    proof = minterjsUtil.toBuffer(proof);
  } else if (options.address || options.privateKey || options.seedPhrase) {
    proof = getProofWithRecovery(options);
  }
  this.txData = new minterjsTx.TxDataRedeemCheck({
    check: minterjsUtil.toBuffer(check),
    proof: proof
  });
  this.proof = proof ? "0x".concat(proof.toString('hex')) : undefined;
  utils.proxyNestedTxData(this);
}

/**
 * @param {object} txData
 * @param {Buffer|string} txData.check
 * @param {Buffer|string} txData.proof
 * @param {TxOptions} [options]
 * @return {RedeemCheckTxData}
 */
RedeemCheckTxData.fromBufferFields = function fromBufferFields(_ref2) {
  var check = _ref2.check,
    proof = _ref2.proof;
  var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  return new RedeemCheckTxData({
    check: check,
    proof: proof
  }, options);
};

/**
 * @param {Buffer|string} data
 * @return {RedeemCheckTxData}
 */
RedeemCheckTxData.fromRlp = function fromRlp(data) {
  return RedeemCheckTxData.fromBufferFields(new minterjsTx.TxDataRedeemCheck(data));
};

/**
 * @param {TxOptions} options
 * @param {ByteArray} options.password
 * @param {ByteArray} [options.address]
 * @param {ByteArray} [options.privateKey]
 * @param {string} [options.seedPhrase]
 * @return {ArrayBuffer|Buffer}
 */
function getProofWithRecovery(_ref3) {
  var password = _ref3.password,
    address = _ref3.address,
    privateKey = _ref3.privateKey,
    seedPhrase = _ref3.seedPhrase;
  var addressBuffer;
  if (address) {
    addressBuffer = minterjsUtil.toBuffer(address);
  } else if (privateKey) {
    privateKey = minterjsUtil.toBuffer(privateKey);
    addressBuffer = minterjsWallet.walletFromPrivateKey(privateKey).getAddress();
  } else if (seedPhrase) {
    addressBuffer = minterjsWallet.walletFromMnemonic(seedPhrase).getAddress();
  } else {
    throw new Error('No address nor seed phrase nor private key given to generate proof');
  }
  var addressHash = hash_js.rlphash([addressBuffer]);

  // ensure Buffer
  password = typeof password === 'string' ? Buffer.from(password, 'utf8') : minterjsUtil.toBuffer(password);
  var passwordBuffer = hash_js.sha256(password);
  var proof = secp256k1.ecdsaSign(addressHash, passwordBuffer);
  var proofWithRecovery = Buffer.alloc(65);
  proofWithRecovery.set(proof.signature, 0);
  proofWithRecovery[64] = proof.recid;
  return proofWithRecovery;
}

module.exports = RedeemCheckTxData;
