'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _regenerator = require('babel-runtime/regenerator');

var _regenerator2 = _interopRequireDefault(_regenerator);

var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator');

var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);

var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');

var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);

var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');

var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);

var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');

var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);

var _inherits2 = require('babel-runtime/helpers/inherits');

var _inherits3 = _interopRequireDefault(_inherits2);

var _ethjs = require('ethjs');

var _ethjs2 = _interopRequireDefault(_ethjs);

var _getContractAddress = require('../../utils/getContractAddress');

var _getContractAddress2 = _interopRequireDefault(_getContractAddress);

var _AbstractContract2 = require('../AbstractContract');

var _AbstractContract3 = _interopRequireDefault(_AbstractContract2);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

/**
 * Arbitrable Abstract Contarct API. This wraps an arbitrable contract. It provides
 * interaction with both the off chain store as well as the arbitrable instance. All
 * arbitrable methods from the supplied contract implementation can be called from this
 * object.
 */
var ArbitrableContract = function (_AbstractContract) {
  (0, _inherits3.default)(ArbitrableContract, _AbstractContract);

  function ArbitrableContract() {
    var _ref;

    var _temp, _this, _ret;

    (0, _classCallCheck3.default)(this, ArbitrableContract);

    for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
      args[_key] = arguments[_key];
    }

    return _ret = (_temp = (_this = (0, _possibleConstructorReturn3.default)(this, (_ref = ArbitrableContract.__proto__ || (0, _getPrototypeOf2.default)(ArbitrableContract)).call.apply(_ref, [this].concat(args))), _this), _initialiseProps.call(_this), _temp), (0, _possibleConstructorReturn3.default)(_this, _ret);
  }
  /**
   * Deploy a contract and add to the Store.
   * @param {string} account - Ethereum address.
   * @param {int} value - funds to be placed in contract.
   * @param {string} hashContract - Keccak hash of the plain English contract.
   * @param {string} arbitratorAddress - The address of the arbitrator contract.
   * @param {int} timeout - Time after which a party automatically loose a dispute.
   * @param {string} partyB - Ethereum address of the other party in the contract.
   * @param {bytes} arbitratorExtraData - Extra data for the arbitrator.
   * @param {string} email - Email address of the contract creator (default empty string).
   * @param {...any} args - Extra arguments for the contract.
   * @returns {object | Error} - The contract object or an error.
   */


  /**
   * Submit evidence. FIXME should we determine the hash for the user?
   * @param {string} account - ETH address of user.
   * @param {string} name - Name of evidence.
   * @param {string} description - Description of evidence.
   * @param {string} url - A link to an evidence using its URI.
   * @param {string} hash - A hash of the evidence at the URI. No hash if content is dynamic
   * @returns {string} - txHash Hash transaction.
   */


  /**
   * Get all contracts TODO do we need to get contract data from blockchain?
   * @param {string} account - Address of user.
   * @returns {object[]} - Contract data from store.
   */


  /**
   * Fetch all data from the store on the current contract.
   * @returns {object} - Store data for contract.
   */


  return ArbitrableContract;
}(_AbstractContract3.default);

var _initialiseProps = function _initialiseProps() {
  var _this2 = this;

  this.deploy = function () {
    var _ref2 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee(account, value, arbitratorAddress, timeout, partyB) {
      for (var _len2 = arguments.length, args = Array(_len2 > 8 ? _len2 - 8 : 0), _key2 = 8; _key2 < _len2; _key2++) {
        args[_key2 - 8] = arguments[_key2];
      }

      var arbitratorExtraData = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : '';

      var _contractImplementati;

      var email = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : '';
      var metaEvidence = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : {};
      var web3Provider, eth, txCount, contractAddress, metaEvidenceUri, contractInstance, newContract;
      return _regenerator2.default.wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              web3Provider = _this2._contractImplementation.getWeb3Provider();
              eth = new _ethjs2.default(web3Provider);
              _context.next = 4;
              return eth.getTransactionCount(account);

            case 4:
              txCount = _context.sent;

              // determine the contract address WARNING if the nonce changes this will produce a different address
              contractAddress = (0, _getContractAddress2.default)(account, txCount);
              metaEvidenceUri = _this2._StoreProvider.getMetaEvidenceUri(account, contractAddress);
              _context.next = 9;
              return (_contractImplementati = _this2._contractImplementation.constructor).deploy.apply(_contractImplementati, [account, value, arbitratorAddress, timeout, partyB, arbitratorExtraData, metaEvidenceUri, web3Provider].concat(args));

            case 9:
              contractInstance = _context.sent;

              if (!(contractInstance.address !== contractAddress)) {
                _context.next = 12;
                break;
              }

              throw new Error('Contract address does not match meta-evidence uri');

            case 12:
              _context.next = 14;
              return _this2._StoreProvider.updateContract(account, contractInstance.address, {
                partyA: account,
                partyB: partyB,
                email: email,
                metaEvidence: metaEvidence
              });

            case 14:
              newContract = _context.sent;
              return _context.abrupt('return', newContract);

            case 16:
            case 'end':
              return _context.stop();
          }
        }
      }, _callee, _this2);
    }));

    return function (_x, _x2, _x3, _x4, _x5) {
      return _ref2.apply(this, arguments);
    };
  }();

  this.submitEvidence = function () {
    var _ref3 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee2(account, name, description, url, hash) {
      var contractAddress, evidenceIndex, evidenceUri, txHash;
      return _regenerator2.default.wrap(function _callee2$(_context2) {
        while (1) {
          switch (_context2.prev = _context2.next) {
            case 0:
              contractAddress = _this2._contractImplementation.contractAddress;
              // get the index of the new evidence

              _context2.next = 3;
              return _this2._StoreProvider.addEvidenceContract(contractAddress, account, name, description, url, hash);

            case 3:
              evidenceIndex = _context2.sent;

              // construct the unique URI
              evidenceUri = _this2._StoreProvider.getEvidenceUri(account, contractAddress, evidenceIndex);
              _context2.next = 7;
              return _this2._contractImplementation.submitEvidence(account, evidenceUri);

            case 7:
              txHash = _context2.sent;
              return _context2.abrupt('return', txHash);

            case 9:
            case 'end':
              return _context2.stop();
          }
        }
      }, _callee2, _this2);
    }));

    return function (_x9, _x10, _x11, _x12, _x13) {
      return _ref3.apply(this, arguments);
    };
  }();

  this.getContractsForUser = function () {
    var _ref4 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee3(account) {
      var userProfile;
      return _regenerator2.default.wrap(function _callee3$(_context3) {
        while (1) {
          switch (_context3.prev = _context3.next) {
            case 0:
              _context3.next = 2;
              return _this2._StoreProvider.newUserProfile(account);

            case 2:
              userProfile = _context3.sent;
              return _context3.abrupt('return', userProfile.contracts);

            case 4:
            case 'end':
              return _context3.stop();
          }
        }
      }, _callee3, _this2);
    }));

    return function (_x14) {
      return _ref4.apply(this, arguments);
    };
  }();

  this.getDataFromStore = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee4() {
    var contractInstance, partyA;
    return _regenerator2.default.wrap(function _callee4$(_context4) {
      while (1) {
        switch (_context4.prev = _context4.next) {
          case 0:
            _context4.next = 2;
            return _this2._contractImplementation.loadContract();

          case 2:
            contractInstance = _context4.sent;
            _context4.next = 5;
            return contractInstance.partyA();

          case 5:
            partyA = _context4.sent;
            return _context4.abrupt('return', _this2._StoreProvider.getContractByAddress(partyA, _this2._contractImplementation.contractAddress));

          case 7:
          case 'end':
            return _context4.stop();
        }
      }
    }, _callee4, _this2);
  }));
};

exports.default = ArbitrableContract;
//# sourceMappingURL=Arbitrable.js.map