contract YieldToken is ERC20 {
	using SafeMath for uint256;
    
    // uint256 private initialSupply_ = 20000000 * 10 ** 18;
	uint256 constant public BURNING_REWARD = 200 ether; 
	uint256 constant public BASE_OG_RATE = 1 ether; 
	uint256 constant public BASE_OW_RATE = 0.25 ether;
	
	mapping(address => uint256) public rewards;
	mapping(address => uint256) public lastUpdate;

	IProject public  projectContract;

	event RewardPaid(address indexed user, uint256 reward);

	constructor(address _project, string memory name_, string memory symbol_, uint256 initialSupply_) ERC20(name_, symbol_) {
		projectContract = IProject(_project);
		_mint(msg.sender, initialSupply_);
	}

    // called when minting
	function updateRewardOnMint(address _user) external {
		require(msg.sender == address(projectContract), "Can't call this");
		uint256 time = block.timestamp;
		uint256 timerUser = lastUpdate[_user];
		
        rewards[_user] += projectContract.balanceOG(_user).mul(BASE_OG_RATE.mul((time.sub(timerUser)))).div(86400);
        rewards[_user] += projectContract.balanceOW(_user).mul(BASE_OW_RATE.mul((time.sub(timerUser)))).div(86400);

		lastUpdate[_user] = time;
	}
	
	// called on transfers
	function updateReward(address _from, address _to) external {
		require(msg.sender == address(projectContract));

        uint256 time = block.timestamp;
        uint256 timerFrom = lastUpdate[_from];
        if (timerFrom > 0) {
            rewards[_from] += projectContract.balanceOG(_from).mul(BASE_OG_RATE.mul((time.sub(timerFrom)))).div(86400);
            rewards[_from] += projectContract.balanceOW(_from).mul(BASE_OW_RATE.mul((time.sub(timerFrom)))).div(86400);
        }
        lastUpdate[_from] = time;
        if (_to != address(0)) {
            uint256 timerTo = lastUpdate[_to];
            if (timerTo > 0) {
                rewards[_to] += projectContract.balanceOG(_to).mul(BASE_OG_RATE.mul((time.sub(timerTo)))).div(86400);
                rewards[_to] += projectContract.balanceOW(_to).mul(BASE_OW_RATE.mul((time.sub(timerTo)))).div(86400);
            }
            lastUpdate[_to] = time;
        }
	}

	function getReward(address _to) external {
		require(msg.sender == address(projectContract));
		uint256 reward = rewards[_to];
		if (reward > 0) {
			rewards[_to] = 0;
			_mint(_to, reward);
			emit RewardPaid(_to, reward);
		}
	}

	function burn(address _from, uint256 _amount) external {
		require(msg.sender == address(projectContract));
		_burn(_from, _amount);
	}

    function burnReward(address _to) external {
		require(msg.sender == address(projectContract));
        _mint(_to, BURNING_REWARD);
	}

	function getTotalClaimable(address _user) external view returns(uint256) {
		uint256 time = block.timestamp;
		uint256 pending = projectContract.balanceOG(_user).mul(BASE_OG_RATE.mul((time.sub(lastUpdate[_user])))).div(86400);
		pending += projectContract.balanceOW(_user).mul(BASE_OW_RATE.mul((time.sub(lastUpdate[_user])))).div(86400);
		return rewards[_user] + pending;
	}
}
function updateReward(address _from, address _to) external {
	require(msg.sender == address(projectContract));

       uint256 time = block.timestamp;
       uint256 timerFrom = lastUpdate[_from];
       if (timerFrom > 0) {
           rewards[_from] += projectContract.balanceOG(_from).mul(BASE_OG_RATE.mul((time.sub(timerFrom)))).div(86400);
           rewards[_from] += projectContract.balanceOW(_from).mul(BASE_OW_RATE.mul((time.sub(timerFrom)))).div(86400);
       }
       lastUpdate[_from] = time;
       if (_to != address(0)) {
           uint256 timerTo = lastUpdate[_to];
           if (timerTo > 0) {
               rewards[_to] += projectContract.balanceOG(_to).mul(BASE_OG_RATE.mul((time.sub(timerTo)))).div(86400);
               rewards[_to] += projectContract.balanceOW(_to).mul(BASE_OW_RATE.mul((time.sub(timerTo)))).div(86400);
           }
           lastUpdate[_to] = time;
       }
}

// called on transfers