contract Depositer is Ownable {
    using SafeERC20 for IERC20;

    address private bouncer;

    IERC20 public immutable moovContract;

    bool public active;

    mapping(address => uint256) public totalWithdrawn;

    constructor(IERC20 _moovContract) {
        moovContract = _moovContract;
        bouncer = msg.sender;
    }

    /*
    /* Users
    */

    event Deposit(address indexed userAddress, uint256 amount);

    function deposit(uint256 _amount) external {
        require(active, "dotmoovs payments are not active");
        require(_amount > 0, "Deposit amount must be positive");

        moovContract.safeTransferFrom(msg.sender, address(this), _amount);

        emit Deposit(msg.sender, _amount);
    }

    event Withdraw(address indexed userAddress, uint256 amount);

    function withdraw(
        uint256 _newTotalWithdrawn,
        uint8 _v,
        bytes32 _r,
        bytes32 _s
    ) external {
        require(active, "dotmoovs payments are not active");

        bytes32 messageHash = keccak256(
            abi.encodePacked(address(this), msg.sender, _newTotalWithdrawn)
        );
        require(
            bouncer ==
                ecrecover(
                    keccak256(
                        abi.encodePacked(
                            "\x19Ethereum Signed Message:\n32",
                            messageHash
                        )
                    ),
                    _v,
                    _r,
                    _s
                ),
            "Invalid signature"
        );

        uint256 userTotalWithdrawn = totalWithdrawn[msg.sender];
        require(_newTotalWithdrawn > userTotalWithdrawn, "Message replay");

        totalWithdrawn[msg.sender] = _newTotalWithdrawn;

        uint256 amountToTransfer = _newTotalWithdrawn - userTotalWithdrawn;
        moovContract.safeTransfer(msg.sender, amountToTransfer);

        emit Withdraw(msg.sender, amountToTransfer);
    }

    /*
    /* Owner
    */

    function setBouncer(address _bouncer) external onlyOwner {
        require(_bouncer != address(0), "Bouncer can't be the zero address");

        bouncer = _bouncer;
    }

    function toggleActive() external onlyOwner {
        active = !active;
    }

    function withdrawFunds(uint256 _amount) external onlyOwner {
        moovContract.safeTransfer(msg.sender, _amount);
    }
}
function setBouncer(address _bouncer) external onlyOwner {
    require(_bouncer != address(0), "Bouncer can't be the zero address");

    bouncer = _bouncer;
}

/*
 /* Owner
 */