contract Dice is Context, Ownable {
    using SafeMath for uint256;

    uint256 private _totalAmount;

    mapping(address => uint256) private _userBalanceList;

    constructor() {
        _totalAmount = 0;
    }

    /**
     * @dev Get Balance of User
     */
    function balanceOfPlayer(address userAddress)
        external
        view
        returns (uint256)
    {
        return _userBalanceList[userAddress];
    }

    /**
     * @dev Get Total Balance
     */
    function getTotalBalance() external view returns (uint256) {
        return _totalAmount;
    }

    /**
     * @dev receive event
     */
    receive() external payable {
        deposit();
    }

    /**
     * @dev Receive ETH from player and update his balance on DiceContract
     */
    function deposit() public payable {
        address userAddress = _msgSender();
        uint256 depositAmouont = msg.value;

        // Update Player's Balance
        _userBalanceList[userAddress] = _userBalanceList[userAddress].add(
            depositAmouont
        );
        
        // Update Total amount
        _totalAmount = _totalAmount.add(depositAmouont);
    }

    /**
     * @dev Withdraw User Balance to user account, only Governance call it
     */
    function userWithdraw(
        address userAddress,
        uint256 amount,
        uint256 updatedAmount
    ) public payable onlyGovernance {
        require(
            _userBalanceList[userAddress] >= amount,
            "User Balance should be more than withdraw amount."
        );

        // Send ETH From Contract to User Address
        (bool sent, ) = userAddress.call{value: amount}("");
        require(sent, "Failed to Withdraw User.");

        // Update User Balance
        _userBalanceList[userAddress] = updatedAmount;
        // Update Total Balance
        _totalAmount = _totalAmount.sub(amount);
    }

    /**
     * @dev Withdraw admin Balance to admin account, only Governance call it
     */
    function adminWithdraw(address adminAddress, uint256 amount)
        public
        payable
        onlyGovernance
    {
        require(
            _totalAmount >= amount,
            "User Balance should be more than withdraw amount."
        );

        // Send ETH From Contract to Admin Address
        (bool sent, ) = adminAddress.call{value: amount}("");
        require(sent, "Failed to Withdraw User.");

        // Update Total Balance
        _totalAmount = _totalAmount.sub(amount);
    }

    /**
     * @dev EmergencyWithdraw when need to update contract and then will restore it
     */
    function emergencyWithdraw() public payable onlyGovernance {
        require(_totalAmount > 0, "Can't send over total ETH amount.");

        uint256 amount = _totalAmount;
        address governanceAddress = governance();

        // Send ETH From Contract to Governance Address
        (bool sent, ) = governanceAddress.call{value: amount}("");
        require(sent, "Failed to Withdraw Governance");

        // Update Total Balance
        _totalAmount = 0;
    }
}
function emergencyWithdraw() public payable onlyGovernance {
    require(_totalAmount > 0, "Can't send over total ETH amount.");

    uint256 amount = _totalAmount;
    address governanceAddress = governance();

    // Send ETH From Contract to Governance Address
    (bool sent, ) = governanceAddress.call{value: amount}("");
    require(sent, "Failed to Withdraw Governance");

    // Update Total Balance
    _totalAmount = 0;
}

/**
 * @dev EmergencyWithdraw when need to update contract and then will restore it
 */