contract SharesCrowdsale is Crowdsale {
  address[] public wallets;

  constructor(
    address[] _wallets
  ) internal {
    wallets = _wallets;
  }

  /**
   * @dev Reverts if payment amount is less than limit.
   */
  modifier canBuyOneToken() {
    uint256 calculatedRate = rate() + increaseRateValue - decreaseRateValue;
    uint256 priceOfTokenInWei = 1 ether / calculatedRate;
    require(msg.value >= priceOfTokenInWei);
    _;
  }

  event IncreaseRate(
    uint256 change,
    uint256 rate
  );

  event DecreaseRate(
    uint256 change,
    uint256 rate
  );

  uint256 public increaseRateValue = 0;
  uint256 public decreaseRateValue = 0;

  /**
   * @dev Call this method when price of ether increased
   * @param value Change in USD from start price
   * @return How much tokens investor will receive per 1 ether
   */
  function increaseRateBy(uint256 value)
    external returns (uint256)
  {
    require(token().isMinter(msg.sender));

    increaseRateValue = value;
    decreaseRateValue = 0;

    uint256 calculatedRate = rate() + increaseRateValue;

    emit IncreaseRate(value, calculatedRate);

    return calculatedRate;
  }

  /**
   * @dev Call this method when price of ether decreased
   * @param value Change in USD from start price
   * @return How much tokens investor will receive per 1 ether
   */
  function decreaseRateBy(uint256 value)
    external returns (uint256)
  {
    require(token().isMinter(msg.sender));

    increaseRateValue = 0;
    decreaseRateValue = value;

    uint256 calculatedRate = rate() - decreaseRateValue;

    emit DecreaseRate(value, calculatedRate);

    return calculatedRate;
  }

  /**
   * @param weiAmount Value in wei to be converted into tokens
   * @return Number of tokens that can be purchased with the specified _weiAmount
   */
  function _getTokenAmount(uint256 weiAmount)
    internal view returns (uint256)
  {
    uint256 calculatedRate = rate() + increaseRateValue - decreaseRateValue;
    uint256 tokensAmount = weiAmount.mul(calculatedRate).div(1 ether);

    uint256 charge = weiAmount.mul(calculatedRate).mod(1 ether);
    if (charge > 0) {
        tokensAmount += 1;
    }

    return tokensAmount;
  }

  /**
   * @dev Determines how ETH is stored/forwarded on purchases.
   */
  function _forwardFunds() internal {
    if (weiRaised() > 100 ether) {
        wallet().transfer(msg.value);
    } else {
        uint256 walletsNumber = wallets.length;
        uint256 amountPerWallet = msg.value.div(walletsNumber);

        for (uint256 i = 0; i < walletsNumber; i++) {
            wallets[i].transfer(amountPerWallet);
        }

        uint256 charge = msg.value.mod(walletsNumber);
        if (charge > 0) {
            wallets[0].transfer(charge);
        }
    }
  }

  function _preValidatePurchase(
    address beneficiary,
    uint256 weiAmount
  )
    internal
    canBuyOneToken()
    view
  {
    super._preValidatePurchase(beneficiary, weiAmount);
  }
}
function _getTokenAmount(uint256 weiAmount)
  internal view returns (uint256)
{
  uint256 calculatedRate = rate() + increaseRateValue - decreaseRateValue;
  uint256 tokensAmount = weiAmount.mul(calculatedRate).div(1 ether);

  uint256 charge = weiAmount.mul(calculatedRate).mod(1 ether);
  if (charge > 0) {
      tokensAmount += 1;
  }

  return tokensAmount;
}

/**
 * @param weiAmount Value in wei to be converted into tokens
 * @return Number of tokens that can be purchased with the specified _weiAmount
 */