contract TokenTimelock {
    using SafeERC20 for IERC20;
    using SafeMath for uint256;

    // ERC20 basic token contract being held
    IERC20 private _token;

    // beneficiary of tokens after they are released
    address internal _beneficiary;

    // timestamp when token release is enabled
    uint256[] internal _releaseTimes;
    // amount when token release is enabled
    uint256[] internal _amounts;

    //Release Status
    mapping (uint => bool) public _releaseStates;

    constructor (IERC20 token, address beneficiary, uint256[] memory releaseTimes, uint256[] memory amounts) public {
        
        require(releaseTimes.length == amounts.length, "Length Checking");
        _token = token;

        for (uint index = 0; index < releaseTimes.length; index++) {
            require(releaseTimes[index] > block.timestamp, "TokenTimelock: release time is before current time");
        }

        _beneficiary = beneficiary;
        _releaseTimes = releaseTimes;
        _amounts = amounts;
    }

    /**
     * @return the token being held.
     */
    function token() public view returns (IERC20) {
        return _token;
    }

    /**
     * @return the beneficiary of the tokens.
     */
    function beneficiary() public view returns (address) {
        return _beneficiary;
    }

    /**
     * @return the time when the tokens are released.
     */
    function releaseTime(uint index) public view returns (uint256) {
        return _releaseTimes[index];
    }

    /**
     * @return the amount when the tokens are released.
     */
    function releaseAmount(uint index) public view returns (uint256) {
        return _amounts[index];
    }

    /**
     * @notice Transfers tokens held by timelock to beneficiary.
     */
    function release() public {
        uint256 amount;
        for (uint index = 0; index < _releaseTimes.length; index++) {
            if(block.timestamp >= _releaseTimes[index] ){
                if(!_releaseStates[index]){
                amount = amount.add(_amounts[index]);
                _releaseStates[index] = true;
                }
            }
        }
        
        require(amount > 0 , "TokenTimelock: no tokens to release");
        require(amount <= _token.balanceOf(address(this)), "TokenTimelock: no enough tokens to release");

        _token.safeTransfer(_beneficiary, amount);
    }
    
    function finishRelease()  public{
        require(_releaseStates[_releaseTimes.length -1]);
        _token.safeTransfer(_beneficiary, _token.balanceOf(address(this)));
    }
}
function releaseAmount(uint index) public view returns (uint256) {
    return _amounts[index];
}

/**
 * @return the amount when the tokens are released.
 */