contract ABIO_BaseICO is Haltable{
    mapping(address => uint256) ethBalances;

    uint public weiRaised;//total raised in wei
    uint public abioSold;//amount of ABIO sold
    uint public volume; //total amount of ABIO selling in this preICO

    uint public startDate;
    uint public length;
    uint public deadline;
    bool public restTokensBurned;

    uint public weiPerABIO; //how much wei one ABIO costs
    uint public minInvestment;
    uint public fundingGoal;
    bool public fundingGoalReached;
    address public treasury;

    ABIO_Token public abioToken;

    event ICOStart(uint volume, uint weiPerABIO, uint minInvestment);
    event SoftcapReached(address recipient, uint totalAmountRaised);
    event FundsReceived(address backer, uint amount);
    event FundsWithdrawn(address receiver, uint amount);

    event ChangeTreasury(address operator, address newTreasury);
    event ChangeMinInvestment(address operator, uint oldMin, uint newMin);

         /**
         * @notice allows owner to change the treasury in case of hack/lost keys.
         * @dev Marked external because it is never called from this contract.
         */
         function changeTreasury(address _newTreasury) external onlyOwner{
             treasury = _newTreasury;
             emit ChangeTreasury(msg.sender, _newTreasury);
         }

         /**
         * @notice allows owner to change the minInvestment in case of extreme price jumps of ETH price.
         */
         function changeMinInvestment(uint _newMin) external onlyOwner{
             emit ChangeMinInvestment(msg.sender, minInvestment, _newMin);
             minInvestment = _newMin;
         }

         /**
          * @notice Called everytime we receive a contribution in ETH.
          * @dev Tokens are immediately transferred to the contributor, even if goal doesn't get reached.
          */
         function () payable stopOnPause{
             require(now < deadline);
             require(msg.value >= minInvestment);
             uint amount = msg.value;
             ethBalances[msg.sender] += amount;
             weiRaised += amount;
             if(!fundingGoalReached && weiRaised >= fundingGoal){goalReached();}

             uint ABIOAmount = amount / weiPerABIO ;
             abioToken.transfer(msg.sender, ABIOAmount);
             abioSold += ABIOAmount;
             emit FundsReceived(msg.sender, amount);
         }

         /**
         * @notice We implement tokenFallback in case someone decides to send us tokens or we want to increase ICO Volume.
         * @dev If someone sends random tokens transaction is reverted.
         * @dev If owner of token sends tokens, we accept them.
         * @dev Crowdsale opens once this contract gets the tokens.
         */
         function tokenFallback(address _from, uint _value, bytes _data) external{
             require(_from == abioToken.owner() || _from == owner);
             volume = _value;
             paused = false;
             deadline = now + length;
             emit ICOStart(_value, weiPerABIO, minInvestment);
         }

         /**
         * @notice Burns tokens leftover from an ICO round.
         * @dev This can be called by anyone after deadline since it's an essential and inevitable part.
         */
         function burnRestTokens() afterDeadline{
                 require(!restTokensBurned);
                 abioToken.burnMyBalance();
                 restTokensBurned = true;
         }

         function isRunning() view returns (bool){
             return (now < deadline);
         }

         function goalReached() internal;

         modifier afterDeadline() { if (now >= deadline) _; }
}
function burnRestTokens() afterDeadline{
        require(!restTokensBurned);
        abioToken.burnMyBalance();
        restTokensBurned = true;
}

/**
 * @notice Burns tokens leftover from an ICO round.
 * @dev This can be called by anyone after deadline since it's an essential and inevitable part.
 */