contract MasterVest is ReentrancyGuard, Ownable {

    using SafeMath for uint256;

    /// @dev Deployed token reference.
    FlameToken public token;
    /// @dev Beneficiary of tokens after they are released.
    address public beneficiary;
    /// @dev Start time of vesting.
    uint256 public start;
    /// @dev Constructor parameter
    uint256 public months;
    /// @dev Holds release amount
    uint256 public released;

    event Released(uint256 amount);

    /// @dev Creates a vesting contract that vests its balance of FlameToken token to the
    /// _multiSigAddress, tokens are released in an linear fashion after a moth 
    /// has passed until _start +  nrOfMonths * months. 
    /// By then all of the balance will have vested.
    /// @param _cap total amount of tokens to be minted 50-50
    /// @param _months vesting period in months
    /// @param _multiSigAddress address of multisig account (the holder of tokens)
    constructor (uint256 _cap, uint _months, address _multiSigAddress) public {

        require(_multiSigAddress != address(0) && _cap != 0 && _months != 0);
        
        beneficiary = _multiSigAddress;
        months = _months;
        token = new FlameToken(_cap);
        start = now;

        initialMint(_cap);
        token.finishMinting();

    }

    /// @dev Callable only by owner to set a new beneficiary for the vesting amount.
    function setBeneficiary(address _newBeneficiary) external onlyOwner {
        beneficiary = _newBeneficiary;
    }

    /// @notice Transfers vested tokens to beneficiary.
    /// @dev Can only be called by beneficiary wich is the multi-sig wallet.
    function release() external nonReentrant onlyBeneficiary {
        uint256 unreleased = releasableAmount(); 
        require(unreleased > 0); 
        released = released.add(unreleased);
        token.transfer(beneficiary, unreleased);
        emit Released(unreleased);
    }

    /// @dev Calculates the amount that has already vested but hasn't been released yet.    
    function releasableAmount() public view returns(uint256) {
        return vestedAmount().sub(released); 
    }

    /// @dev Calculates the amount that has already vested.
    function vestedAmount() public view returns(uint256) {

        uint256 currentBalance = token.balanceOf(this); 
        uint256 totalBalance = currentBalance.add(released); 

        if (now < start) {
            return 0;
        }
        uint256 dT = now.sub(start); // time passed since start
        uint256 dMonths = dT.div(30 days); // months passed 

        if (dMonths >= months) {
            return totalBalance; // return everything if vesting period ended
        } else {
            return totalBalance.mul(dMonths).div(months); // ammount = total * (months passed / total months)
        }

    }

    /// @notice Directly mints half of value and vests the other healf for the same beneficiary.
    function initialMint(uint256 _cap) internal {
        uint256 halfCap = _cap.div(2);
        // 50% of vested amount minted in contract
        token.mint(this, halfCap);
        // 50% of vested amount minted directly for multisig wallet
        token.mint(beneficiary, _cap.sub(halfCap));
    }

    /// @dev Modifier that makes sure that only beneficiary, in our case multisig wallet can call this.
    modifier onlyBeneficiary() {
        require(msg.sender == beneficiary);
        _;
    }

}
/**
 * @title MasterVest
 * @dev A token holder contract that can release its token balance linear.
 * @dev A sum equal to amount/months will be released every month.
 */
function setBeneficiary(address _newBeneficiary) external onlyOwner {
    beneficiary = _newBeneficiary;
}

/// @dev Callable only by owner to set a new beneficiary for the vesting amount.