import _slicedToArray from 'babel-runtime/helpers/slicedToArray';
import _Promise from 'babel-runtime/core-js/promise';
import _JSON$stringify from 'babel-runtime/core-js/json/stringify';
import _regeneratorRuntime from 'babel-runtime/regenerator';
import _asyncToGenerator from 'babel-runtime/helpers/asyncToGenerator';
import _Object$getPrototypeOf from 'babel-runtime/core-js/object/get-prototype-of';
import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
import _inherits from 'babel-runtime/helpers/inherits';

var _this2 = this;

import arbitrableTransactionArtifact from 'kleros-interaction/build/contracts/ArbitrableTransaction';
import _ from 'lodash';

import * as ethConstants from '../../../constants/eth';
import * as contractConstants from '../../../constants/contract';
import * as errorConstants from '../../../constants/error';
import ContractImplementation from '../../ContractImplementation';
import deployContractAsync from '../../../utils/deployContractAsync';

/**
 * Provides interaction with an Arbitrable Transaction contract deployed on the blockchain.
 */

var ArbitrableTransaction = function (_ContractImplementati) {
  _inherits(ArbitrableTransaction, _ContractImplementati);

  /**
   * Constructor ArbitrableTransaction.
   * @param {object} web3Provider instance
   * @param {string} contractAddress of the contract
   */
  function ArbitrableTransaction(web3Provider, contractAddress) {
    _classCallCheck(this, ArbitrableTransaction);

    var _this = _possibleConstructorReturn(this, (ArbitrableTransaction.__proto__ || _Object$getPrototypeOf(ArbitrableTransaction)).call(this, web3Provider, arbitrableTransactionArtifact, contractAddress));

    _initialiseProps.call(_this);

    return _this;
  }

  /**
   * Deploy ArbitrableTransaction.
   * @param {object} account Ethereum account (default account[0])
   * @param {number} value funds to be placed in contract
   * @param {string} hashContract Keccak hash of the plain English contract. (default null hashed)
   * @param {string} arbitratorAddress The address of the arbitrator contract
   * @param {number} timeout Time after which a party automatically loose a dispute. (default 3600)
   * @param {string} partyB The recipient of the transaction. (default account[1])
   * @param {bytes} arbitratorExtraData Extra data for the arbitrator. (default empty string)
   * @param {object} web3Provider web3 provider object
   * @returns {object} truffle-contract Object | err The deployed contract or an error
   */


  /**
   * Pay the party B. To be called when the good is delivered or the service rendered.
   * @param {string} account - Ethereum account (default account[0]).
   * @param {string} contractAddress - The address of the arbitrator contract.
   * @returns {object} - The result transaction object.
   */


  /**
   * Pay the arbitration fee to raise a dispute. To be called by the party A.
   * @param {string} account - Ethereum account (default account[0]).
   * @param {number} arbitrationCost - Amount to pay the arbitrator. (default 10000 wei).
   * @returns {object} - The result transaction object.
   */


  /**
   * Pay the arbitration fee to raise a dispute. To be called by the party B.
   * @param {string} account Ethereum account (default account[1]).
   * @param {number} arbitrationCost Amount to pay the arbitrator. (default 10000 wei).
   * @returns {object} - The result transaction object.
   */


  /**
   * Submit evidence.
   * @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.
   * @returns {string} txHash Hash transaction.
   */


  /**
   * Call by partyA if partyB is timeout
   * @param {string} account ETH address of user
   * @returns {object} The result transaction object.
   */


  /**
   * Call by partyB if partyA is timeout.
   * @param {string} account - ETH address of user.
   * @param {string} contractAddress - ETH address of contract.
   * @returns {object} The result transaction object.
   */


  /**
   * Get ruling options from dispute via event
   * @param {string} arbitratorAddress address of arbitrator contract
   * @param {number} disputeId index of dispute
   * @returns {object[]} an array of objects that specify the name and value of the resolution option
   */


  /**
   * Data of the contract
   * @returns {object} Object Data of the contract.
   */


  return ArbitrableTransaction;
}(ContractImplementation);

ArbitrableTransaction.deploy = function () {
  var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(account) {
    var value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ethConstants.TRANSACTION.VALUE;
    var hashContract = arguments[2];
    var arbitratorAddress = arguments[3];
    var timeout = arguments[4];
    var partyB = arguments[5];
    var arbitratorExtraData = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : '';
    var web3Provider = arguments[7];
    var contractDeployed;
    return _regeneratorRuntime.wrap(function _callee$(_context) {
      while (1) {
        switch (_context.prev = _context.next) {
          case 0:
            _context.next = 2;
            return deployContractAsync(account, value, arbitrableTransactionArtifact, web3Provider, arbitratorAddress, hashContract, timeout, partyB, arbitratorExtraData);

          case 2:
            contractDeployed = _context.sent;
            return _context.abrupt('return', contractDeployed);

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

  return function (_x) {
    return _ref.apply(this, arguments);
  };
}();

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

  this.pay = function () {
    var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
      var account = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _this3._Web3Wrapper.getAccount(0);
      return _regeneratorRuntime.wrap(function _callee2$(_context2) {
        while (1) {
          switch (_context2.prev = _context2.next) {
            case 0:
              _context2.next = 2;
              return _this3.loadContract();

            case 2:
              _context2.prev = 2;
              return _context2.abrupt('return', _this3.contractInstance.pay({
                from: account,
                gas: ethConstants.TRANSACTION.GAS,
                value: 0
              }));

            case 6:
              _context2.prev = 6;
              _context2.t0 = _context2['catch'](2);

              console.error(_context2.t0);
              throw new Error(errorConstants.UNABLE_TO_PAY_SELLER);

            case 10:
            case 'end':
              return _context2.stop();
          }
        }
      }, _callee2, _this3, [[2, 6]]);
    }));

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

  this.payArbitrationFeeByPartyA = function () {
    var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3() {
      var account = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _this3._Web3Wrapper.getAccount(0);
      var arbitrationCost = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0.15;
      return _regeneratorRuntime.wrap(function _callee3$(_context3) {
        while (1) {
          switch (_context3.prev = _context3.next) {
            case 0:
              _context3.next = 2;
              return _this3.loadContract();

            case 2:
              _context3.prev = 2;
              return _context3.abrupt('return', _this3.contractInstance.payArbitrationFeeByPartyA({
                from: account,
                gas: ethConstants.TRANSACTION.GAS,
                value: _this3._Web3Wrapper.toWei(arbitrationCost, 'ether')
              }));

            case 6:
              _context3.prev = 6;
              _context3.t0 = _context3['catch'](2);

              console.error(_context3.t0);
              throw new Error(errorConstants.UNABLE_TO_PAY_ARBITRATION_FEE);

            case 10:
            case 'end':
              return _context3.stop();
          }
        }
      }, _callee3, _this3, [[2, 6]]);
    }));

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

  this.payArbitrationFeeByPartyB = function () {
    var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee4() {
      var account = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _this3._Web3Wrapper.getAccount(1);
      var arbitrationCost = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0.15;
      return _regeneratorRuntime.wrap(function _callee4$(_context4) {
        while (1) {
          switch (_context4.prev = _context4.next) {
            case 0:
              _context4.next = 2;
              return _this3.loadContract();

            case 2:
              _context4.prev = 2;
              return _context4.abrupt('return', _this3.contractInstance.payArbitrationFeeByPartyB({
                from: account,
                gas: ethConstants.TRANSACTION.GAS,
                value: _this3._Web3Wrapper.toWei(arbitrationCost, 'ether')
              }));

            case 6:
              _context4.prev = 6;
              _context4.t0 = _context4['catch'](2);

              console.error(_context4.t0);
              throw new Error(errorConstants.UNABLE_TO_PAY_ARBITRATION_FEE);

            case 10:
            case 'end':
              return _context4.stop();
          }
        }
      }, _callee4, _this3, [[2, 6]]);
    }));

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

  this.submitEvidence = function () {
    var _ref5 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee5() {
      var account = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _this3._Web3Wrapper.getAccount(0);
      var name = arguments[1];
      var description = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
      var url = arguments[3];
      var txHashObj;
      return _regeneratorRuntime.wrap(function _callee5$(_context5) {
        while (1) {
          switch (_context5.prev = _context5.next) {
            case 0:
              _context5.next = 2;
              return _this3.loadContract();

            case 2:
              _context5.next = 4;
              return _this3.contractInstance.submitEvidence(_JSON$stringify(name, description, url), {
                from: account,
                gas: ethConstants.TRANSACTION.GAS,
                value: 0
              });

            case 4:
              txHashObj = _context5.sent;
              return _context5.abrupt('return', txHashObj.tx);

            case 6:
            case 'end':
              return _context5.stop();
          }
        }
      }, _callee5, _this3);
    }));

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

  this.callTimeOutPartyA = function () {
    var _ref6 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee6() {
      var account = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _this3._Web3Wrapper.getAccount(0);
      var status, timeout, lastInteraction;
      return _regeneratorRuntime.wrap(function _callee6$(_context6) {
        while (1) {
          switch (_context6.prev = _context6.next) {
            case 0:
              _context6.next = 2;
              return _this3.loadContract();

            case 2:
              _context6.next = 4;
              return _this3.contractInstance.status();

            case 4:
              status = _context6.sent.toNumber();
              _context6.next = 7;
              return _this3.contractInstance.timeout();

            case 7:
              timeout = _context6.sent.toNumber();
              _context6.next = 10;
              return _this3.contractInstance.lastInteraction();

            case 10:
              lastInteraction = _context6.sent.toNumber();

              if (!(status !== contractConstants.STATUS.WAITING_PARTY_B)) {
                _context6.next = 15;
                break;
              }

              throw new Error(errorConstants.CONTRACT_IS_NOT_WAITING_ON_OTHER_PARTY);

            case 15:
              if (!(Date.now() >= lastInteraction + timeout)) {
                _context6.next = 17;
                break;
              }

              throw new Error(errorConstants.TIMEOUT_NOT_REACHED);

            case 17:
              _context6.prev = 17;
              return _context6.abrupt('return', _this3.contractInstance.timeOutByPartyA({
                from: account,
                gas: ethConstants.TRANSACTION.GAS,
                value: 0
              }));

            case 21:
              _context6.prev = 21;
              _context6.t0 = _context6['catch'](17);

              console.error(_context6.t0);
              throw new Error(errorConstants.UNABLE_TO_CALL_TIMEOUT);

            case 25:
            case 'end':
              return _context6.stop();
          }
        }
      }, _callee6, _this3, [[17, 21]]);
    }));

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

  this.callTimeOutPartyB = function () {
    var _ref7 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee7() {
      var account = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _this3._Web3Wrapper.getAccount(1);
      var status, timeout, lastInteraction;
      return _regeneratorRuntime.wrap(function _callee7$(_context7) {
        while (1) {
          switch (_context7.prev = _context7.next) {
            case 0:
              _context7.next = 2;
              return _this3.loadContract();

            case 2:
              _context7.next = 4;
              return _this3.contractInstance.status();

            case 4:
              status = _context7.sent;
              _context7.next = 7;
              return _this3.contractInstance.timeout();

            case 7:
              timeout = _context7.sent;
              _context7.next = 10;
              return _this3.contractInstance.lastInteraction();

            case 10:
              lastInteraction = _context7.sent;

              if (!(status !== contractConstants.STATUS.WAITING_PARTY_A)) {
                _context7.next = 15;
                break;
              }

              throw new Error(errorConstants.CONTRACT_IS_NOT_WAITING_ON_OTHER_PARTY);

            case 15:
              if (!(Date.now() >= lastInteraction + timeout)) {
                _context7.next = 17;
                break;
              }

              throw new Error(errorConstants.TIMEOUT_NOT_REACHED);

            case 17:
              _context7.prev = 17;
              return _context7.abrupt('return', _this3.contractInstance.timeOutByPartyB({
                from: account,
                gas: ethConstants.TRANSACTION.GAS,
                value: 0
              }));

            case 21:
              _context7.prev = 21;
              _context7.t0 = _context7['catch'](17);

              console.error(_context7.t0);
              throw new Error(errorConstants.UNABLE_TO_CALL_TIMEOUT);

            case 25:
            case 'end':
              return _context7.stop();
          }
        }
      }, _callee7, _this3, [[17, 21]]);
    }));

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

  this.getRulingOptions = function () {
    var _ref8 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee8(arbitratorAddress, disputeId) {
      var statusNumber, disputeEvents, disputeOption, rulingOptions, optionIndex, resolutionOptions;
      return _regeneratorRuntime.wrap(function _callee8$(_context8) {
        while (1) {
          switch (_context8.prev = _context8.next) {
            case 0:
              _context8.next = 2;
              return _this3.loadContract();

            case 2:
              _context8.next = 4;
              return _this3.contractInstance.status();

            case 4:
              statusNumber = _context8.sent.toNumber();

              if (!(statusNumber < contractConstants.STATUS.DISPUTE_CREATED)) {
                _context8.next = 7;
                break;
              }

              return _context8.abrupt('return', []);

            case 7:
              _context8.next = 9;
              return new _Promise(function (resolve, reject) {
                _this3.contractInstance.Dispute({}, { fromBlock: 0, toBlock: 'latest' }).get(function (error, eventResult) {
                  if (error) reject(error);

                  resolve(eventResult);
                });
              });

            case 9:
              disputeEvents = _context8.sent;
              disputeOption = _.filter(disputeEvents, function (event) {
                var optionDisputeId = event.args._disputeID.toNumber();
                // filter by arbitrator address and disputeId
                return event.args._arbitrator === arbitratorAddress && optionDisputeId === disputeId;
              });
              // should only be 1 at this point

              if (!(disputeOption.length !== 1)) {
                _context8.next = 13;
                break;
              }

              return _context8.abrupt('return', []);

            case 13:
              rulingOptions = disputeOption[0].args._rulingOptions.split(';');
              optionIndex = 0;
              resolutionOptions = rulingOptions.map(function (option) {
                optionIndex += 1;
                return {
                  name: option,
                  value: optionIndex
                };
              });
              return _context8.abrupt('return', resolutionOptions);

            case 17:
            case 'end':
              return _context8.stop();
          }
        }
      }, _callee8, _this3);
    }));

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

  this.getData = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee9() {
    var _ref10, _ref11, arbitrator, extraData, timeout, partyA, partyB, status, arbitratorExtraData, disputeId, partyAFee, partyBFee, lastInteraction, amount;

    return _regeneratorRuntime.wrap(function _callee9$(_context9) {
      while (1) {
        switch (_context9.prev = _context9.next) {
          case 0:
            _context9.next = 2;
            return _this3.loadContract();

          case 2:
            _context9.next = 4;
            return _Promise.all([_this3.contractInstance.arbitrator(), _this3.contractInstance.arbitratorExtraData(),
            //  this.contractInstance.hashContract(),
            _this3.contractInstance.timeout(), _this3.contractInstance.partyA(), _this3.contractInstance.partyB(), _this3.contractInstance.status(), _this3.contractInstance.arbitratorExtraData(), _this3.contractInstance.disputeID(), _this3.contractInstance.partyAFee(), _this3.contractInstance.partyBFee(), _this3.contractInstance.lastInteraction(), _this3.contractInstance.amount()]);

          case 4:
            _ref10 = _context9.sent;
            _ref11 = _slicedToArray(_ref10, 12);
            arbitrator = _ref11[0];
            extraData = _ref11[1];
            timeout = _ref11[2];
            partyA = _ref11[3];
            partyB = _ref11[4];
            status = _ref11[5];
            arbitratorExtraData = _ref11[6];
            disputeId = _ref11[7];
            partyAFee = _ref11[8];
            partyBFee = _ref11[9];
            lastInteraction = _ref11[10];
            amount = _ref11[11];
            return _context9.abrupt('return', {
              address: _this3.getContractAddress(),
              arbitrator: arbitrator,
              extraData: extraData,
              timeout: timeout.toNumber(),
              partyA: partyA,
              partyB: partyB,
              status: status.toNumber(),
              arbitratorExtraData: arbitratorExtraData,
              disputeId: disputeId.toNumber(),
              partyAFee: _this3._Web3Wrapper.fromWei(partyAFee, 'ether'),
              partyBFee: _this3._Web3Wrapper.fromWei(partyBFee, 'ether'),
              lastInteraction: lastInteraction.toNumber(),
              amount: amount.toNumber()
            });

          case 19:
          case 'end':
            return _context9.stop();
        }
      }
    }, _callee9, _this3);
  }));
};

export default ArbitrableTransaction;
//# sourceMappingURL=ArbitrableTransaction.js.map