contract PostDeliveryCrowdsale is TimedCrowdsale, FinalizableCrowdsale {
    using SafeMath for uint256;

    // minimum amount of funds to be raised in weis
    uint256 private _goal;

    mapping(address => uint256) private _balances;
    __unstable__TokenVault private _vault;

    constructor (uint256 goal) public {
        require(goal > 0, "RefundableCrowdsale: goal is 0");
        _vault = new __unstable__TokenVault();
        _goal = goal;
    }

    /**
     * @dev Withdraw tokens only after crowdsale ends.
     * @param beneficiary Whose tokens will be withdrawn.
     */
    function withdrawTokens(address beneficiary) public {
       require(goalReached(), "RefundableCrowdsale: goal not reached");
       //require(hasClosed(), "PostDeliveryCrowdsale: not closed");
       require(finalized(), "Withdraw Tokens: crowdsale not finalized");
        uint256 amount = _balances[beneficiary];
        require(amount > 0, "PostDeliveryCrowdsale: beneficiary is not due any tokens");

        _balances[beneficiary] = 0;
        //_vault.transfer(token(), beneficiary, amount); //so taxes are avoided
        _deliverTokens(address(beneficiary), amount);
    }

     /**
     * @dev Checks whether funding goal was reached.
     * @return Whether funding goal was reached
     */
    function goalReached() public view returns (bool) {
        return weiRaised() >= _goal;
    }

    /**
     * @return the balance of an account.
     */
    function balanceOf(address account) public view returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev Overrides parent by storing due balances, and delivering tokens to the vault instead of the end user. This
     * ensures that the tokens will be available by the time they are withdrawn (which may not be the case if
     * `_deliverTokens` was called later).
     * @param beneficiary Token purchaser
     * @param tokenAmount Amount of tokens purchased
     */
    function _processPurchase(address beneficiary, uint256 tokenAmount) internal {
        _balances[beneficiary] = _balances[beneficiary].add(tokenAmount);
       // _deliverTokens(address(_vault), tokenAmount); //so taxes are avoided
    }
}
/**
 * @title PostDeliveryCrowdsale
 * @dev Crowdsale that locks tokens from withdrawal until it ends.
 */
function withdrawTokens(address beneficiary) public {
   require(goalReached(), "RefundableCrowdsale: goal not reached");
   //require(hasClosed(), "PostDeliveryCrowdsale: not closed");
   require(finalized(), "Withdraw Tokens: crowdsale not finalized");
    uint256 amount = _balances[beneficiary];
    require(amount > 0, "PostDeliveryCrowdsale: beneficiary is not due any tokens");

    _balances[beneficiary] = 0;
    //_vault.transfer(token(), beneficiary, amount); //so taxes are avoided
    _deliverTokens(address(beneficiary), amount);
}

/**
 * @dev Withdraw tokens only after crowdsale ends.
 * @param beneficiary Whose tokens will be withdrawn.
 */