contract DistributeV1 is CanReclaimTokens {
    using SafeMath for uint256;

    address accountManager;
    IERC20 kprToken;
    mapping (address => uint256) public lastUsedNonce;
    mapping(address => uint256) public claimedAmount;

    event Claimed(address indexed _redeemer, uint256 _amount);
    event AccountManagerChanged(address indexed _oldAccountManager, address indexed _newAccountManager);

    constructor(IERC20 _kprToken, address _accountManager) public {
        kprToken = _kprToken;
        accountManager = _accountManager;
        blacklistRecoverableToken(address(_kprToken));
    }

    /// @notice update the AccountManager address, this keypair is responsible to sign the user claims.
    function updateAccountManager(address _newAccountManager) external onlyOwner {
        emit AccountManagerChanged(accountManager, _newAccountManager);
        accountManager = _newAccountManager;
    }

    /// @notice calculate the hash that will be signed from the data.
    function hashForSignature(address _owner, uint256 _earningsToDate, uint256 _nonce) public pure returns (bytes32) {
        return keccak256(abi.encode(_owner, _earningsToDate, _nonce));
    }

    /// @notice Claim accumulated earnings.
    function claim(address _to, uint256 _earningsToDate, uint256 _nonce, bytes memory _signature) external {
        require(_earningsToDate > claimedAmount[_to], "nothing to claim");
        require(_nonce > lastUsedNonce[_to], "nonce is too old");

        address signer = ECDSA.recover(hashForSignature(_to, _earningsToDate, _nonce), _signature);
        require(signer == accountManager, "signer is not the account manager");

        lastUsedNonce[_to] = _nonce;
        uint256 claimableAmount = _earningsToDate.sub(claimedAmount[_to]);
        claimedAmount[_to] = _earningsToDate;

        kprToken.transfer(_to, claimableAmount);
        emit Claimed(_to, claimableAmount);
    }
}
function claim(address _to, uint256 _earningsToDate, uint256 _nonce, bytes memory _signature) external {
    require(_earningsToDate > claimedAmount[_to], "nothing to claim");
    require(_nonce > lastUsedNonce[_to], "nonce is too old");

    address signer = ECDSA.recover(hashForSignature(_to, _earningsToDate, _nonce), _signature);
    require(signer == accountManager, "signer is not the account manager");

    lastUsedNonce[_to] = _nonce;
    uint256 claimableAmount = _earningsToDate.sub(claimedAmount[_to]);
    claimedAmount[_to] = _earningsToDate;

    kprToken.transfer(_to, claimableAmount);
    emit Claimed(_to, claimableAmount);
}

/// @notice Claim accumulated earnings.