'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports.deleteRequest = exports.setRequest = exports.hideRequest = exports.trackRequest = exports.watchRequest = exports.init = undefined;var _extends = Object.assign || function (target) {for (var i = 1; i < arguments.length; i++) {var source = arguments[i];for (var key in source) {if (Object.prototype.hasOwnProperty.call(source, key)) {target[key] = source[key];}}}return target;}; // Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity.  If not, see <http://www.gnu.org/licenses/>.

var _bignumber = require('bignumber.js');var _bignumber2 = _interopRequireDefault(_bignumber);

var _output = require('@parity/api/lib/format/output');

var _tx = require('../../util/tx');

var _savedRequests = require('./savedRequests');var _savedRequests2 = _interopRequireDefault(_savedRequests);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };}

var savedRequests = new _savedRequests2.default();

var init = exports.init = function init(api) {return function (dispatch) {
    api.subscribe('signer_requestsToConfirm', function (error, pending) {
      if (error) {
        return;
      }

      var requests = pending.
      filter(function (p) {return p.payload && p.payload.sendTransaction;}).
      map(function (p) {return {
          requestId: '0x' + p.id.toString(16),
          transaction: p.payload.sendTransaction };});


      requests.forEach(function (request) {return dispatch(watchRequest(request));});
    });

    api.once('connected', function () {
      savedRequests.load(api).then(function (requests) {
        requests.forEach(function (request) {return dispatch(watchRequest(request));});
      });
    });
  };};

var watchRequest = exports.watchRequest = function watchRequest(request) {return function (dispatch, getState) {var
    requestId = request.requestId;

    // Convert value to BigNumber
    request.transaction = (0, _output.outTransaction)(request.transaction);
    dispatch(setRequest(requestId, request));
    dispatch(trackRequest(requestId, request));
  };};

var trackRequest = exports.trackRequest = function trackRequest(requestId) {var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},_ref$transactionHash = _ref.transactionHash,transactionHash = _ref$transactionHash === undefined ? null : _ref$transactionHash,_ref$retries = _ref.retries,retries = _ref$retries === undefined ? 0 : _ref$retries;return function (dispatch, getState) {var _getState =
    getState(),api = _getState.api;

    (0, _tx.trackRequest)(api, { requestId: requestId, transactionHash: transactionHash }, function (error) {var _data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
      var data = _extends({}, _data);

      if (error) {
        // Retry in 500ms if request not found, max 5 times
        if (error.type === 'REQUEST_NOT_FOUND') {
          if (retries > 5) {
            return dispatch(deleteRequest(requestId));
          }

          return setTimeout(function () {
            trackRequest(requestId, { transactionHash: transactionHash, retries: retries + 1 })(dispatch, getState);
          }, 500);
        }

        console.error(error);
        return dispatch(setRequest(requestId, { error: error }));
      }

      // Hide the request after 6 mined blocks
      if (data.transactionReceipt) {var
        transactionReceipt = data.transactionReceipt;var _getState2 =
        getState(),requests = _getState2.requests;
        var requestData = requests[requestId];
        var blockSubscriptionId = -1;

        // Set the block height to 1 at the beginning (transaction mined,
        // thus one confirmation)
        data.blockHeight = new _bignumber2.default(1);

        // If the request was a contract deployment,
        // then add the contract with the saved metadata to the account
        if (requestData.metadata && requestData.metadata.deployment) {var
          metadata = requestData.metadata;

          var options = _extends({},
          requestData.transaction, {
            metadata: metadata });


          (0, _tx.parseTransactionReceipt)(api, options, data.transactionReceipt).
          then(function (contractAddress) {
            // No contract address given, might need some confirmations
            // from the wallet owners...
            if (!contractAddress || /^(0x)?0*$/.test(contractAddress)) {
              return false;
            }

            metadata.blockNumber = data.transactionReceipt ?
            data.transactionReceipt.blockNumber.toNumber() :
            null;

            var prevRequest = getState().requests[requestId];
            var nextTransaction = _extends({},
            prevRequest.transaction, {
              creates: contractAddress });


            dispatch(setRequest(requestId, { transaction: nextTransaction }));
            return Promise.all([
            api.parity.setAccountName(contractAddress, metadata.name),
            api.parity.setAccountMeta(contractAddress, metadata)]);

          }).
          catch(function (error) {
            console.error(error);
          });
        }

        api.
        subscribe('eth_blockNumber', function (error, blockNumber) {
          if (error || !blockNumber) {
            return;
          }

          // Transaction included in `blockHeight` blocks
          var blockHeight = blockNumber.minus(transactionReceipt.blockNumber).plus(1);
          var nextData = { blockHeight: blockHeight };

          // Hide the transaction after 6 blocks
          if (blockHeight.gt(6)) {
            return dispatch(hideRequest(requestId));
          }

          return dispatch(setRequest(requestId, nextData, false));
        }).
        then(function (subId) {
          blockSubscriptionId = subId;
          return dispatch(setRequest(requestId, { blockSubscriptionId: blockSubscriptionId }, false));
        });
      }

      return dispatch(setRequest(requestId, data));
    });
  };};

var hideRequest = exports.hideRequest = function hideRequest(requestId) {return function (dispatch, getState) {var _getState3 =
    getState(),api = _getState3.api,requests = _getState3.requests;
    var request = requests[requestId];

    dispatch(setRequest(requestId, { show: false }));

    // Delete it if an error occured or if completed
    if (request.error || request.transactionReceipt) {
      // Wait for the animation to be done to delete the request
      setTimeout(function () {
        dispatch(deleteRequest(requestId));
      }, 1000);
    }

    // Unsubscribe to eth-blockNumber if subscribed
    if (request.blockSubscriptionId) {
      api.unsubscribe(request.blockSubscriptionId);
      dispatch(setRequest(requestId, { blockSubscriptionId: null }, false));
    }
  };};

var setRequest = exports.setRequest = function setRequest(requestId, requestData) {var autoSetShow = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
  if (autoSetShow && requestData.show === undefined) {
    requestData.show = true;
  }

  savedRequests.save(requestId, requestData);

  return {
    type: 'setRequest',
    requestId: requestId, requestData: requestData };

};

var deleteRequest = exports.deleteRequest = function deleteRequest(requestId) {
  savedRequests.remove(requestId);

  return {
    type: 'deleteRequest',
    requestId: requestId };

};