contract Crowdsale {
  using SafeMath for uint256;

  // The token being sold
  StandardToken public token;

  // How many token units a buyer gets per wei
  uint256 public rate;

  // How many token units a buyer gets per wei if entitled to the presale
  uint public presaleRate;

  // Amount of wei raised
  uint256 public weiRaised;

  // Administrator of the sale
  address public owner;

  // How many tokens each address bought at the normal rate
  mapping (address => uint) public regularTokensSold;

  // How many tokens each address bought at the presale rate
  mapping (address => uint) public presaleTokensSold;

  // List of all the investors
  address[] public investors;

  // Whether the sale is active
  bool public inSale = true;

  // Whether the presale is active
  bool public inPresale = true;

  // How many tokens each address can buy at the presale rate
  mapping (address => uint) public presaleAllocations;

  // The total number of tokens bought
  uint256 public totalPresaleTokensSold = 0;

  // The total number of tokens bought
  uint256 public totalRegularTokensSold = 0;

  // The maximum number of tokens which can be sold during presale
  uint256 constant public PRESALETOKENMAXSALES = 15000000000000000000000000;

  // The maximum number of tokens which can be sold during regular sale
  uint256 public regularTokenMaxSales = 16000000000000000000000000;

  // The minimum investment (5 ETH) during presale
  uint256 constant public MINIMUMINVESTMENTPRESALE = 5000000000000000000;

  // The minimum investment (5 ETH) during sale
  uint256 constant public MINIMUMINVESTMENTSALE = 1000000000000000000;

  modifier onlyOwner() {
    require(msg.sender == owner);
    _;
  }

  modifier onlyDuringPresale() {
    require(inPresale);
    _;
  }

  modifier onlyWhenSalesEnabled() {
    require(inSale);
    _;
  }

  /**
   * Event for token purchase logging
   * @param purchaser who paid for the tokens
   * @param beneficiary who got the tokens
   * @param value weis paid for purchase
   * @param amount amount of tokens purchased
   * @param rate the rate at which the tokens were purchased
   */
  event TokenPurchase(address indexed purchaser, address indexed beneficiary, uint256 value, uint256 amount, uint256 rate);

  /**
   * Constructor for the crowdsale
   * @param _owner owner of the contract, which can call privileged functions, and where every ether
   *        is sent to
   * @param _rate the rate for regular sales
   * @param _rate the rate for presales
   * @param _ownerInitialTokens the number of tokens the owner is allocated initially
   */
  function Crowdsale(
    address _owner, 
    uint256 _rate, 
    uint256 _presaleRate, 
    uint256 _ownerInitialTokens
  ) public payable {
    require(_rate > 0);
    require(_presaleRate > 0);
    require(_owner != address(0));

    rate = _rate;
    presaleRate = _presaleRate;
    owner = _owner;

    investors.push(owner);
    regularTokensSold[owner] = _ownerInitialTokens;
  }

  // -----------------------------------------
  // Crowdsale external interface
  // -----------------------------------------

  function () external payable {
    buyTokens();
  }

  /**
   * Sets the address of the Token contract.
   */
  function setToken(StandardToken _token) public onlyOwner {
    token = _token;
  }

  /**
   * Buy a token at presale price. Converts ETH to as much QNT the sender can purchase. Any change
   * is refunded to the sender. Minimum contribution is 5 ETH.
   */
  function buyPresaleTokens() onlyDuringPresale onlyWhenSalesEnabled public payable {
    address _beneficiary = msg.sender;
    uint256 weiAmount = msg.value;

    _preValidatePurchase(_beneficiary);
    require(weiAmount >= MINIMUMINVESTMENTPRESALE);

    uint256 presaleAllocation = presaleAllocations[_beneficiary];

    uint256 presaleTokens = _min256(weiAmount.mul(presaleRate), presaleAllocation);

    _recordPresalePurchase(_beneficiary, presaleTokens);

    // Remove presale tokens allocation
    presaleAllocations[_beneficiary] = presaleAllocations[_beneficiary].sub(presaleTokens);

    uint256 weiCharged = presaleTokens.div(presaleRate);

    // Return any extra Wei to the sender
    uint256 change = weiAmount.sub(weiCharged);
    _beneficiary.transfer(change);

    // Update total number of Wei raised
    weiRaised = weiRaised.add(weiAmount.sub(change));

    emit TokenPurchase(msg.sender, _beneficiary, weiCharged, presaleTokens, presaleRate);

    // Forward the funds to owner
    _forwardFunds(weiCharged);
  }

  /**
   * Buy a token at sale price. Minimum contribution is 1 ETH.
   */
  function buyTokens() onlyWhenSalesEnabled public payable {
    address _beneficiary = msg.sender;
    uint256 weiAmount = msg.value;
    _preValidatePurchase(_beneficiary);

    require(weiAmount >= MINIMUMINVESTMENTSALE);

    uint256 tokens = weiAmount.mul(rate);

    // Check we haven't sold too many tokens
    totalRegularTokensSold = totalRegularTokensSold.add(tokens);
    require(totalRegularTokensSold <= regularTokenMaxSales);

    // Update total number of Wei raised
    weiRaised = weiRaised.add(weiAmount);

    investors.push(_beneficiary);

    // Give tokens
    regularTokensSold[_beneficiary] = regularTokensSold[_beneficiary].add(tokens);

    emit TokenPurchase(msg.sender, _beneficiary, weiAmount, tokens, rate);

    // Forward the funds to owner
    _forwardFunds(weiAmount);
  }

  /**
   * Records a purchase which has been completed before the instantiation of this contract.
   * @param _beneficiary the investor
   * @param _presaleTokens the number of tokens which the investor has bought
   */
  function recordPresalePurchase(address _beneficiary, uint256 _presaleTokens) public onlyOwner {
    weiRaised = weiRaised.add(_presaleTokens.div(presaleRate));
    return _recordPresalePurchase(_beneficiary, _presaleTokens);
  }

  function enableSale() onlyOwner public {
    inSale = true;
  }

  function disableSale() onlyOwner public {
    inSale = false;
  }

  function endPresale() onlyOwner public {
    inPresale = false;

    // Convert the unsold presale tokens to regular tokens
    uint256 remainingPresaleTokens = PRESALETOKENMAXSALES.sub(totalPresaleTokensSold);
    regularTokenMaxSales = regularTokenMaxSales.add(remainingPresaleTokens);
  }

  /**
   * Mints the tokens in the Token contract.
   */
  function transferTokens() public onlyOwner {
    for (uint256 i = 0; i < investors.length; i = i.add(1)) {
      address investor = investors[i];

      uint256 tokens = regularTokensSold[investor];
      uint256 presaleTokens = presaleTokensSold[investor];
      
      regularTokensSold[investor] = 0;
      presaleTokensSold[investor] = 0;

      if (tokens > 0) {
        _deliverTokens(token, investor, tokens);
      }

      if (presaleTokens > 0) {
        _deliverTokens(token, investor, presaleTokens);
      }
    }
  }

  /**
   * Mints the tokens in the Token contract. With Offset and Limit
   */
  function transferTokensWithOffsetAndLimit(uint256 offset, uint256 limit) public onlyOwner {
    for (uint256 i = offset; i <  _min256(investors.length,offset+limit); i = i.add(1)) {
      address investor = investors[i];

      uint256 tokens = regularTokensSold[investor];
      uint256 presaleTokens = presaleTokensSold[investor];

      regularTokensSold[investor] = 0;
      presaleTokensSold[investor] = 0;

      if (tokens > 0) {
        _deliverTokens(token, investor, tokens);
      }

      if (presaleTokens > 0) {
        _deliverTokens(token, investor, presaleTokens);
      }
    }
  }


  /**
   * Clears the number of tokens bought by an investor. The ETH refund needs to be processed
   * manually.
   */
  function refund(address investor) onlyOwner public {
    require(investor != owner);

    uint256 regularTokens = regularTokensSold[investor];
    totalRegularTokensSold = totalRegularTokensSold.sub(regularTokens);
    weiRaised = weiRaised.sub(regularTokens.div(rate));

    uint256 presaleTokens = presaleTokensSold[investor];
    totalPresaleTokensSold = totalPresaleTokensSold.sub(presaleTokens);
    weiRaised = weiRaised.sub(presaleTokens.div(presaleRate));

    regularTokensSold[investor] = 0;
    presaleTokensSold[investor] = 0;

    // Manually send ether to the account
  }

  /**
  * Accessor for Index
  */
  function getInvestorAtIndex(uint256 _index) public view returns(address) {
    return investors[_index];
  }

  /**
  * Return the length of the investors array
  */
  function getInvestorsLength() public view returns(uint256) {
    return investors.length;
  }

  /**
   * Get the number of tokens bought at the regular price for an address.
   */
  function getNumRegularTokensBought(address _address) public view returns(uint256) {
    return regularTokensSold[_address];
  }

  /**
   * Get the number of tokens bought at the presale price for an address.
   */
  function getNumPresaleTokensBought(address _address) public view returns(uint256) {
    return presaleTokensSold[_address];
  }

  /**
   * Get the number of tokens which an investor can purchase at presale rate.
   */
  function getPresaleAllocation(address investor) view public returns(uint256) {
    return presaleAllocations[investor];
  }

  /**
   * Set the number of tokens which an investor can purchase at presale rate.
   */
  function setPresaleAllocation(address investor, uint allocation) onlyOwner public {
    presaleAllocations[investor] = allocation;
  }

  // -----------------------------------------
  // Internal interface (extensible)
  // -----------------------------------------

  /**
   * @dev Validation of an incoming purchase. Use require statements to revert state when conditions are not met. Use super to concatenate validations.
   * @param _beneficiary Address performing the token purchase
   */
  function _preValidatePurchase(address _beneficiary) internal pure {
    require(_beneficiary != address(0));
  }

  /**
   * @dev Source of tokens. Override this method to modify the way in which the crowdsale ultimately gets and sends its tokens.
   * @param _beneficiary Address performing the token purchase
   * @param _tokenAmount Number of tokens to be emitted
   */
  function _deliverTokens(StandardToken _token, address _beneficiary, uint256 _tokenAmount) internal {
    _token.mint(_beneficiary, _tokenAmount);
  }

  /**
   * @dev Determines how ETH is stored/forwarded on purchases.
   */
  function _forwardFunds(uint256 amount) internal {
    owner.transfer(amount);
  }

  function _min256(uint256 a, uint256 b) internal pure returns (uint256) {
    return a < b ? a : b;
  }

  /**
   * Records a presale purchase.
   * @param _beneficiary the investor
   * @param _presaleTokens the number of tokens which the investor has bought
   */
  function _recordPresalePurchase(address _beneficiary, uint256 _presaleTokens) internal {
    // Check we haven't sold too many presale tokens
    totalPresaleTokensSold = totalPresaleTokensSold.add(_presaleTokens);
    require(totalPresaleTokensSold <= PRESALETOKENMAXSALES);

    investors.push(_beneficiary);

    // Give presale tokens
    presaleTokensSold[_beneficiary] = presaleTokensSold[_beneficiary].add(_presaleTokens);
  }
}
/**
 * @title Crowdsale
 * @dev Crowdsale is a base contract for managing a token crowdsale,
 * allowing investors to purchase tokens with ether.
 * The external interface represents the basic interface for purchasing tokens, and conform
 * the base architecture for crowdsales. 
 *
 * Presales:
 * Certain addresses are allowed to buy at a presale rate during the presale period. The
 * contribution of the investor needs to be of at least 5 ETH. A maximum of 15 million tokens
 * in total can be bought at the presale rate. Once the presale has been instructed to end, it
 * is not possible to enable it again.
 *
 * Sales:
 * Any address can purchase at the regular sale price. Sales can be pauses, resumed, and stopped.
 *
 * Minting:
 * The transferTokens function will mint the tokens in the Token contract. After the minting 
 * is done, the Crowdsale is reset.
 * 
 * Refunds:
 * A investor can be refunded by the owner. Calling the refund function resets the tokens bought
 * to zero for that investor. The Ether refund needs to be processed manually. It is important
 * to record how many tokens the investor had bought before calling refund().
 *
 */
function buyPresaleTokens() onlyDuringPresale onlyWhenSalesEnabled public payable {
  address _beneficiary = msg.sender;
  uint256 weiAmount = msg.value;

  _preValidatePurchase(_beneficiary);
  require(weiAmount >= MINIMUMINVESTMENTPRESALE);

  uint256 presaleAllocation = presaleAllocations[_beneficiary];

  uint256 presaleTokens = _min256(weiAmount.mul(presaleRate), presaleAllocation);

  _recordPresalePurchase(_beneficiary, presaleTokens);

  // Remove presale tokens allocation
  presaleAllocations[_beneficiary] = presaleAllocations[_beneficiary].sub(presaleTokens);

  uint256 weiCharged = presaleTokens.div(presaleRate);

  // Return any extra Wei to the sender
  uint256 change = weiAmount.sub(weiCharged);
  _beneficiary.transfer(change);

  // Update total number of Wei raised
  weiRaised = weiRaised.add(weiAmount.sub(change));

  emit TokenPurchase(msg.sender, _beneficiary, weiCharged, presaleTokens, presaleRate);

  // Forward the funds to owner
  _forwardFunds(weiCharged);
}

/**
 * Buy a token at presale price. Converts ETH to as much QNT the sender can purchase. Any change
 * is refunded to the sender. Minimum contribution is 5 ETH.
 */