function buyTokensInternal(address _beneficiary, uint256 _bonus) internal returns (uint256) {
      require(!finalized);
      require(!suspended);
      require(currentTime() >= startTime);
      require(currentTime() <= endTime);
      require(msg.value >= contributionMin);
      require(_beneficiary != address(0));
      require(_beneficiary != address(this));
      require(_beneficiary != address(token));

      
      
      require(msg.sender != address(walletAddress));

      
      uint256 saleBalance = token.balanceOf(address(this));
      require(saleBalance > 0);

      
      uint256 tokens = msg.value.mul(tokensPerKEther).mul(_bonus.add(10000)).div(tokenConversionFactor);
      require(tokens > 0);

      uint256 cost = msg.value;
      uint256 refund = 0;

      
      
      uint256 maxTokens = saleBalance;

      if (maxTokensPerAccount > 0) {
         
         
         uint256 userBalance = getUserTokenBalance(_beneficiary);
         require(userBalance < maxTokensPerAccount);

         uint256 quotaBalance = maxTokensPerAccount.sub(userBalance);

         if (quotaBalance < saleBalance) {
            maxTokens = quotaBalance;
         }
      }

      require(maxTokens > 0);

      if (tokens > maxTokens) {
         
         
         tokens = maxTokens;

         
         cost = tokens.mul(tokenConversionFactor).div(tokensPerKEther.mul(_bonus.add(10000)));

         if (msg.value > cost) {
            
            
            refund = msg.value.sub(cost);
         }
      }

      
      uint256 contribution = msg.value.sub(refund);
      walletAddress.transfer(contribution);

      
      totalTokensSold     = totalTokensSold.add(tokens);
      totalEtherCollected = totalEtherCollected.add(contribution);

      
      require(token.transfer(_beneficiary, tokens));

      
      if (refund > 0) {
         msg.sender.transfer(refund);
      }

      emit TokensPurchased(_beneficiary, cost, tokens);

      return tokens;
   }