contract ManagerLock is Ownable {

    event Release(address from, uint256 value);
    event Unlock();
    event Lock();

    // ERC20 basic token contract being held
    ERC20 public token;

    // beneficiary of tokens after they are released
    address public beneficiary;

    // lock flag
    bool public locked = true;

    constructor(ERC20 _token, address _owner, address _beneficiary)
    public {
        token = _token;
        beneficiary = _beneficiary;
        owner = _owner;
    }

    modifier notLocked() {
        require(locked == false);
        _;
    }

    /**
    * @dev it releases all tokens held by this contract to beneficiary.
    */
    function release() external {
        uint256 balance = token.balanceOf(address(this));
        partialRelease(balance);
    }

    /**
    * @dev it releases some tokens held by this contract to beneficiary.
    * @param _amount the number of tokens to be sent to beneficiary
    */
    function partialRelease(uint256 _amount) notLocked public {
        //restrict this tx to the legit beneficiary only
        require(msg.sender == beneficiary);

        uint256 balance = token.balanceOf(address(this));
        require(balance >= _amount);
        require(_amount > 0);

        require(token.transfer(beneficiary, _amount));
        emit Release(beneficiary, _amount);
    }

    function unLock() onlyOwner public {
        locked = false;
        emit Unlock();
    }

    function lock() onlyOwner public {
        locked = true;
        emit Lock();
    }
}
function partialRelease(uint256 _amount) notLocked public {
    //restrict this tx to the legit beneficiary only
    require(msg.sender == beneficiary);

    uint256 balance = token.balanceOf(address(this));
    require(balance >= _amount);
    require(_amount > 0);

    require(token.transfer(beneficiary, _amount));
    emit Release(beneficiary, _amount);
}

/**
 * @dev it releases some tokens held by this contract to beneficiary.
 * @param _amount the number of tokens to be sent to beneficiary
 */