contract Crowdsale is Ownable, usingOraclize {
  using SafeMath for uint256;

  // The token being sold
  MITToken public token;

  // address where funds are collected
  address public wallet = 0x009853E2660158638CE92e89f06DedaFF6627066;
  address public TokensWallet = 0xA40E21E432C68C0c8975C7e470Ec8202b3293Df2;
  
  //owner tokens percent
  uint256 OwnerTokensPercent = 15;

  // how many token units a buyer gets per wei
  uint256 public price = 4347826086956521; // 1$ ;

  // amount of raised money in wei
  uint256 public weiRaised = 0;
  
    uint256 public startPreICO = 1537819200; //25 Sep 2018 00:00:00 GMT 
    uint256 public FinishPreICO = 1543089600; //25 nov 2018 00:00:00 GMT
    uint256 public startICO = 1543089600; //25 nov 2018 00:00:00 GMT
    uint256 public FinishICO = 1545681600; //25 dec 2019 00:00:00 GMT
    
    uint256 public tokenDec = 1000000000000000000; //18
    
    uint256 public ICOHardcap = 20000000;
    uint256 public tokensSold = 0;

  constructor() public {
    token = createTokenContract();
  }

  // creates the token to be sold.
  // override this method to have crowdsale of a specific mintable token.
  function createTokenContract() internal returns (MITToken) {
    return new MITToken();
  }

  // fallback function can be used to buy tokens
  function () public payable {
    buyTokens(msg.sender);
  }

  // low level token purchase function
  function buyTokens(address beneficiary) public payable {
    require(beneficiary != 0x0);
    require(validPurchase());
    require(!hasEnded());
    
    updatePrice();

    uint256 weiAmount = msg.value;
    uint256 updatedWeiRaised = weiRaised.add(weiAmount);
    
    uint256 tokens = 0;
    
    // calculate token amount to be created
    if(now >= startPreICO && now < FinishPreICO){
        tokens = weiAmount.mul(tokenDec).div(price).div(tokenDec);
    }
    
    if(now >= startICO && now < FinishICO){
        tokens = weiAmount.mul(tokenDec).div(price.mul(2)).div(tokenDec);
    }
    
    uint256 updatedTokensSold = tokensSold.add(tokens);
    
    if(updatedTokensSold > ICOHardcap){
        tokens = ICOHardcap.sub(tokensSold);
        updatedTokensSold = ICOHardcap;
    }
    
    // update amount tokens
    tokensSold = updatedTokensSold;
        
    token.mint(beneficiary, tokens);
    
    // update state
    weiRaised = updatedWeiRaised;
    
    forwardFunds();
  }
  
    function __callback (bytes32 myid, string result) public {
        if (msg.sender != oraclize_cbAddress()) revert();
        price = tokenDec.div(parseInt(result));
        updatePrice();
    }
    
    function updatePrice() public payable {
        if (oraclize_getPrice("URL") < this.balance) {
            oraclize_query(86400, "URL", "json(https://api.gdax.com/products/ETH-USD/ticker).price");
        }
    }

  // send ether to the fund collection wallet
  // override to create custom fund forwarding mechanisms
  function forwardFunds() internal {
    uint contractBalance = this.balance;
    if(contractBalance > tokenDec.div(10)){
        uint sendingValue = contractBalance.sub(tokenDec.div(10));
        wallet.transfer(sendingValue);
    }
  }
  
  // @return true if the transaction can buy tokens
  function validPurchase() internal constant returns (bool) {
    bool withinPeriod = (now >= startPreICO && now < FinishPreICO) || (now >= startICO && now < FinishICO);
    bool canSoldTokens = ICOHardcap > tokensSold;
    bool nonZeroPurchase = false;
    if(now >= startPreICO && now < FinishPreICO){
        nonZeroPurchase = msg.value >= price;
    }
    if(now >= startICO && now < FinishICO){
        nonZeroPurchase = msg.value >= price.mul(2);
    }
    
    return withinPeriod && nonZeroPurchase && canSoldTokens;
  }
  
  // @return true if crowdsale event has ended
  function hasEnded() public constant returns (bool) {
    return ((now > FinishICO) || (tokensSold >= ICOHardcap));
  }
  
  function setHardcap(uint newHardcap) public onlyOwner {
    ICOHardcap = newHardcap;
  }
  
  function setWallet(address newWallet) public onlyOwner {
    wallet = newWallet;
  }
  
  function setTokensWallet(address newTokensWallet) public onlyOwner { 
    TokensWallet = newTokensWallet;
  }
  
  function setStartPreICO(uint newStartPreICO) public onlyOwner {
    startPreICO = newStartPreICO;
  }
  
  function setFinishPreICO(uint newFinishPreICO) public onlyOwner {
    FinishPreICO = newFinishPreICO;
  }
  
  function setStartICO(uint newStartICO) public onlyOwner {
    startICO = newStartICO;
  }
  
  function setFinishICO(uint newFinishICO) public onlyOwner {
    FinishICO = newFinishICO;
  }
  
  function tokenOperationsFinished() public onlyOwner {
    require(hasEnded());
    token.finishMinting();
    uint OwnerTokens = tokensSold.mul(OwnerTokensPercent).div(100);
    token.mint(TokensWallet, OwnerTokens);
  }
}
function createTokenContract() internal returns (MITToken) {
  return new MITToken();
}

// creates the token to be sold.
// override this method to have crowdsale of a specific mintable token.