contract MDICOStage2 is BaseICO {
  using SafeMath for uint;

  /// @dev 18 decimals for token
  uint internal constant ONE_TOKEN = 1e18;

  /// @dev 1e18 WEI == 1ETH == 1000 tokens
  uint public constant ETH_TOKEN_EXCHANGE_RATIO = 1000;

  /// @dev 0% bonus for ICO Stage 2
  uint8 internal constant BONUS = 0; // 0%

  function MDICOStage2(address icoToken_,
                    address teamWallet_,
                    uint lowCapWei_,
                    uint hardCapWei_,
                    uint lowCapTxWei_,
                    uint hardCapTxWei_) public {
    require(icoToken_ != address(0) && teamWallet_ != address(0));
    token = BaseICOToken(icoToken_);
    teamWallet = teamWallet_;
    state = State.Inactive;
    lowCapWei = lowCapWei_;
    hardCapWei = hardCapWei_;
    lowCapTxWei = lowCapTxWei_;
    hardCapTxWei = hardCapTxWei_;
  }

  /**
   * @dev Recalculate ICO state based on current block time.
   * Should be called periodically by ICO owner.
   */
  function touch() public {
    if (state != State.Active && state != State.Suspended) {
      return;
    }
    if (collectedWei >= hardCapWei) {
      state = State.Completed;
      endAt = block.timestamp;
      ICOCompleted(collectedWei);
    } else if (block.timestamp >= endAt) {
      if (collectedWei < lowCapWei) {
        state = State.NotCompleted;
        ICONotCompleted();
      } else {
        state = State.Completed;
        ICOCompleted(collectedWei);
      }
    }
  }

  function buyTokens() public payable {
    require(state == State.Active &&
            block.timestamp <= endAt &&
            msg.value >= lowCapTxWei &&
            msg.value <= hardCapTxWei &&
            collectedWei + msg.value <= hardCapWei &&
            whitelisted(msg.sender));
    uint amountWei = msg.value;
    uint iwei = amountWei.mul(100 + BONUS).div(100);
    uint itokens = iwei * ETH_TOKEN_EXCHANGE_RATIO;
    token.icoInvestment(msg.sender, itokens); // Transfer tokens to investor
    collectedWei = collectedWei.add(amountWei);
    ICOInvestment(msg.sender, amountWei, itokens, BONUS);
    forwardFunds();
    touch();
  }

  /**
   * Accept direct payments
   */
  function() external payable {
    buyTokens();
  }
}
/**
 * @title MD tokens ICO Stage 2 contract.
 */
function touch() public {
  if (state != State.Active && state != State.Suspended) {
    return;
  }
  if (collectedWei >= hardCapWei) {
    state = State.Completed;
    endAt = block.timestamp;
    ICOCompleted(collectedWei);
  } else if (block.timestamp >= endAt) {
    if (collectedWei < lowCapWei) {
      state = State.NotCompleted;
      ICONotCompleted();
    } else {
      state = State.Completed;
      ICOCompleted(collectedWei);
    }
  }
}

/**
 * @dev Recalculate ICO state based on current block time.
 * Should be called periodically by ICO owner.
 */