contract BankWallet is SafeMath, Owned {
    Casino public edgelessCasino;
    
    mapping(address => uint) public tokenToLimit; 
    
    bool public paused = false;

    event Transfer(address _token, address _receiver, uint _amount);
    event Withdrawal(address _token, address _receiver, uint _amount);
    event Paused(bool _paused);

    constructor(address _casino) public {
        edgelessCasino = Casino(_casino);
        owner = msg.sender;
    }

    /**
     * Allow ether to be received.
     */
    function () external payable {}
    
    /**
     * @param _token      Asset contract (0x0 for eth) to transfer 
     * @param _receiver   Asset receiver wallet address
     * @param _amount     How much to transfer
     */
    function transfer(address _token, address _receiver, uint _amount) public onlyActive onlyAuthorized returns (bool _success) {
        require(tokenToLimit[_token] == 0 || tokenToLimit[_token] >= _amount, "Amount exceeds transfer limit for asset.");
        _success = _transfer(_token, _receiver, _amount);
        if (_success) {
            emit Transfer(_token, _receiver, _amount);
        }
    }

    /**
     * Allow owner to withdraw assets.
     * @param _token      Asset contract (0x0 for eth) to transfer 
     * @param _receiver   Asset receiver wallet address
     * @param _amount     How much to transfer
     */
    function adminTransfer(address _token, address _receiver, uint _amount) public onlyOwner returns (bool _success) {
        _success = _transfer(_token, _receiver, _amount);
        if (_success) {
            emit Withdrawal(_token, _receiver, _amount);
        }
    }
    
    /**
     * @param _token      Asset contract (0x0 for eth) to transfer 
     * @param _receiver   Asset receiver wallet address
     * @param _amount     How much to transfer
     */ 
    function _transfer(address _token, address _receiver, uint _amount) internal returns (bool _success) {
        require(_receiver != address(0), "Please use valid receiver wallet address.");
        _success = false;
        if (_token == address (0)) {
            require(_amount <= address(this).balance, "Eth balance is too small.");
            assert(_success = address(uint160(_receiver)).send(_amount));
        } else {
            ERC20Token __token = ERC20Token(_token);
            require(_amount <= __token.balanceOf(address(this)), "Asset balance is too small.");
            _success = __token.transfer(_receiver, _amount);
        }
    }
    
    /**
     * Set how much of asset can contract transfer with single transaction.
     * @param _token address of token or 0x0 if its eth.
     * @param _limit limit of maximum amount for one transaction. 
     */
    function setTokenLimit(address _token, uint _limit) public onlyOwner {
        tokenToLimit[_token] = _limit;
    }
    
    /**
     * Pause contract in case of emergency or upgrade.
     */ 
    function pause() public onlyActive onlyAuthorized {
        paused = true;
        emit Paused(paused);
    }

    /**
     * Resume transfers from contract.
     */ 
    function activate() public onlyPaused onlyOwner {
        paused = false;
        emit Paused(paused);
    }
    
    modifier onlyAuthorized {
        require(edgelessCasino.authorized(msg.sender), "Sender is not authorized.");
        _;
    }
    
    modifier onlyPaused {
        require(paused == true, "Contract is not paused.");
        _;
    }

    modifier onlyActive {
        require(paused == false, "Contract is paused.");
        _;
    }
}
function activate() public onlyPaused onlyOwner {
    paused = false;
    emit Paused(paused);
}

/**
 * Resume transfers from contract.
 */