// Solidity 0.4.25
/// ===============================================================================================================
///                                      Public Functions - Executors Only
/// ===============================================================================================================
/// @dev Registers a new pull payment to the PumaPay Pull Payment Contract - The registration can be executed only by one of the executors of the PumaPay Pull Payment Contract
/// and the PumaPay Pull Payment Contract checks that the pull payment has been singed by the client of the account.
/// The balance of the executor (msg.sender) is checked and if funding is needed 1 ETH is transferred.
/// Emits 'LogPaymentRegistered' with client address, beneficiary address and paymentID.
/// @param v - recovery ID of the ETH signature. - https://github.com/ethereum/EIPs/issues/155
/// @param r - R output of ECDSA signature.
/// @param s - S output of ECDSA signature.
/// @param _merchantID - ID of the merchant.
/// @param _paymentID - ID of the payment.
/// @param _client - client address that is linked to this pull payment.
/// @param _beneficiary - address that is allowed to execute this pull payment.
/// @param _currency - currency of the payment / 3-letter abbr i.e. 'EUR'.
/// @param _fiatAmountInCents - payment amount in fiat in cents.
/// @param _frequency - how often merchant can pull - in seconds.
/// @param _numberOfPayments - amount of pull payments merchant can make
/// @param _startTimestamp - when subscription starts - in seconds.
function registerPullPayment(
        uint8 v,
        bytes32 r,
        bytes32 s,
        string _merchantID,
        string _paymentID,
        address _client,
        address _beneficiary,
        string _currency,
        uint256 _initialPaymentAmountInCents,
        uint256 _fiatAmountInCents,
        uint256 _frequency,
        uint256 _numberOfPayments,
        uint256 _startTimestamp
    )
    public
    isExecutor()
    {
        require(
            bytes(_paymentID).length > 0 &&
            bytes(_currency).length > 0 &&
            _client != address(0) &&
            _beneficiary != address(0) &&
            _fiatAmountInCents > 0 &&
            _frequency > 0 &&
            _frequency < OVERFLOW_LIMITER_NUMBER &&
            _numberOfPayments > 0 &&
            _startTimestamp > 0 &&
            _startTimestamp < OVERFLOW_LIMITER_NUMBER
        );

        pullPayments[_client][_beneficiary].currency = _currency;
        pullPayments[_client][_beneficiary].initialPaymentAmountInCents = _initialPaymentAmountInCents;
        pullPayments[_client][_beneficiary].fiatAmountInCents = _fiatAmountInCents;
        pullPayments[_client][_beneficiary].frequency = _frequency;
        pullPayments[_client][_beneficiary].startTimestamp = _startTimestamp;
        pullPayments[_client][_beneficiary].numberOfPayments = _numberOfPayments;

        require(isValidRegistration(v, r, s, _client, _beneficiary, pullPayments[_client][_beneficiary]));

        pullPayments[_client][_beneficiary].merchantID = _merchantID;
        pullPayments[_client][_beneficiary].paymentID = _paymentID;
        pullPayments[_client][_beneficiary].nextPaymentTimestamp = _startTimestamp;
        pullPayments[_client][_beneficiary].lastPaymentTimestamp = 0;
        pullPayments[_client][_beneficiary].cancelTimestamp = 0;

        if (isFundingNeeded(msg.sender)) {
            msg.sender.transfer(0.5 ether);
        }

        emit LogPaymentRegistered(_client, _beneficiary, _paymentID);
    }