contract EmpowBonus {
    
    event Bonus(address indexed _address, uint32 indexed dapp_id, uint256 _time, uint256 _bonus_amount, uint256 _pay_amount);
    
    struct BonusHistory {
        address user;
        uint32 dapp_id;
        uint256 time;
        uint32 pay_type;
        uint256 bonus_amount;
        uint256 pay_amount;
    }
    
    mapping (address => uint256) public countBonus;
    mapping (address => mapping (uint256 => BonusHistory)) public bonusHistories;
    
    address public owner;
    address public USDTAddress;
    
    modifier onlyOwner () {
        require(msg.sender == owner);
        _;
    }
    
    function EmpowBonus ()
        public
    {
        owner = msg.sender;
    }
    
    function bonus (uint32 _dapp_id, uint256 _bonus_amount)
        public
        payable
        returns(bool)
    {
        require(msg.value > 0);
        
        countBonus[msg.sender]++;
        
        uint256 currentTime = block.timestamp;
        
        Bonus(msg.sender, _dapp_id, 0, _bonus_amount, msg.value);
        saveHistory(msg.sender, _dapp_id, currentTime, 0, _bonus_amount, msg.value); // pay_type (0 = ETH, 1 = USDT)
        
        return true;
    }
    
    function bonusWithUsdt (uint32 _dapp_id, uint256 _bonus_amount, uint256 _amount_usdt)
        public
        returns(bool)
    {
        require(_amount_usdt > 0);
        // transfer USDT
        require(ERC20(USDTAddress).transferFrom(msg.sender, owner, _amount_usdt));
        
        countBonus[msg.sender]++;
        
        uint256 currentTime = block.timestamp;
        
        Bonus(msg.sender, _dapp_id, 1, _bonus_amount, _amount_usdt);
        saveHistory(msg.sender, _dapp_id, currentTime, 1, _bonus_amount, _amount_usdt); // pay_type (0 = ETH, 1 = USDT)
    }
    
    function saveHistory (address _address, uint32 _dapp_id, uint256 _time, uint32 _pay_type, uint256 _bonus_amount, uint256 _pay_amount)
        private
        returns(bool)
    {
        bonusHistories[msg.sender][countBonus[_address]].user = _address;
        bonusHistories[msg.sender][countBonus[_address]].dapp_id = _dapp_id;
        bonusHistories[msg.sender][countBonus[_address]].time = _time;
        bonusHistories[msg.sender][countBonus[_address]].pay_type = _pay_type;
        bonusHistories[msg.sender][countBonus[_address]].bonus_amount = _bonus_amount;
        bonusHistories[msg.sender][countBonus[_address]].pay_amount = _pay_amount;
        return true;
    }
    
    // OWNER functions
    function updateUSDTAddress (address _address)
        public
        onlyOwner
        returns (bool)
    {
        USDTAddress = _address;
        return true;
    }
    
    function withdraw (uint256 _amount) 
        public
        onlyOwner
        returns (bool)
    {
        owner.transfer(_amount);
        return true;
    }
}
function updateUSDTAddress (address _address)
        public
        onlyOwner
        returns (bool)
    {
        USDTAddress = _address;
        return true;
    }
// OWNER functions