contract DistributeToken is StandardToken, Ownable{

  event AirDrop(address from, address to, uint amount);
  event CrowdDistribute(address from, address to, uint amount);

  using SafeMathLib for uint;

  /* The finalizer contract that allows Distribute token */
  address public distAgent;

  uint public maxAirDrop = 1000*10**18;//need below 1000 TTG

  uint public havedAirDrop = 0;
  uint public totalAirDrop = 0; //totalSupply * 5%

  bool public finishCrowdCoin = false;
  uint public havedCrowdCoin = 0;
  uint public totalCrowdCoin = 0; //totalSupply * 50%

  uint public havedDistDevCoin = 0;
  uint public totalDevCoin = 0;  //totalSupply * 20%

  uint public havedDistFoundCoin = 0;
  uint public totalFoundCoin = 0;  //totalSupply * 20%

  /**
   * 0：1：100000；1：1：50000 2：1：25000  3：1：12500  4：1：12500
   */
  uint private crowState = 0;//
  /**
   * .
   */
  function setDistributeAgent(address addr) onlyOwner  public {
     
     require(addr != address(0));

    // We don't do interface check here as we might want to a normal wallet address to act as a release agent
    distAgent = addr;
  }


  /** The function can be called only by a whitelisted release agent. */
  modifier onlyDistributeAgent() {
    require(msg.sender == distAgent) ;
    _;
  }

  /* Withdraw */
  /*
    NOTICE: These functions withdraw the ETH which remained in the contract account when user call CrowdDistribute
  */
  function withdrawAll () onlyOwner() public {
    owner.transfer(this.balance);
  }

  function withdrawAmount (uint256 _amount) onlyOwner() public {
    owner.transfer(_amount);
  }

 /**发token给基金会*/
 function distributeToFound(address receiver, uint amount) onlyOwner() public  returns (uint actual){ 
  
    require((amount+havedDistFoundCoin) < totalFoundCoin);
  
    balances[owner] = balances[owner].sub(amount);
    balances[receiver] = balances[receiver].plus(amount);
    havedDistFoundCoin = havedDistFoundCoin.plus(amount);

    addFound(receiver);

    // This will make the mint transaction apper in EtherScan.io
    // We can remove this after there is a standardized minting event
    emit Transfer(0, receiver, amount);
   
    return amount;
 }

 /**发token给开发者*/
 function  distributeToDev(address receiver, uint amount) onlyOwner()  public  returns (uint actual){

    require((amount+havedDistDevCoin) < totalDevCoin);

    balances[owner] = balances[owner].sub(amount);
    balances[receiver] = balances[receiver].plus(amount);
    havedDistDevCoin = havedDistDevCoin.plus(amount);

    addDeveloper(receiver);
    // This will make the mint transaction apper in EtherScan.io
    // We can remove this after there is a standardized minting event
    emit Transfer(0, receiver, amount);

    return amount;
 }

 /**空投总量及单次量由发行者来控制， agent不能修改，空投接口只能由授权的agent进行*/
 function airDrop(address transmitter, address receiver, uint amount) public  returns (uint actual){

    require(receiver != address(0));
    require(amount <= maxAirDrop);
    require((amount+havedAirDrop) < totalAirDrop);
    require(transmitter == distAgent);

    balances[owner] = balances[owner].sub(amount);
    balances[receiver] = balances[receiver].plus(amount);
    havedAirDrop = havedAirDrop.plus(amount);

    // This will make the mint transaction apper in EtherScan.io
    // We can remove this after there is a standardized minting event
    emit AirDrop(0, receiver, amount);

    return amount;
  }

 /**用户ICO众筹，由用户发固定的ETH，回馈用户固定的TTG，并添加ICO账户，控制交易规则*/
 function crowdDistribution() payable public  returns (uint actual) {
      
    require(msg.sender != address(0));
    require(!isContract(msg.sender));
    require(msg.value != 0);
    require(totalCrowdCoin > havedCrowdCoin);
    require(finishCrowdCoin == false);
    
    uint actualAmount = calculateCrowdAmount(msg.value);

    require(actualAmount != 0);

    havedCrowdCoin = havedCrowdCoin.plus(actualAmount);
    balances[owner] = balances[owner].sub(actualAmount);
    balances[msg.sender] = balances[msg.sender].plus(actualAmount);
    
    switchCrowdState();
    
    // This will make the mint transaction apper in EtherScan.io
    // We can remove this after there is a standardized minting event
    emit CrowdDistribute(0, msg.sender, actualAmount);

    return actualAmount;
  }

 function  switchCrowdState () internal{

    if (havedCrowdCoin < totalCrowdCoin.mul(10).div(100) ){
       crowState = 0;

    }else  if (havedCrowdCoin < totalCrowdCoin.mul(20).div(100) ){
       crowState = 1;
    
    } else if (havedCrowdCoin < totalCrowdCoin.mul(30).div(100) ){
       crowState = 2;

    } else if (havedCrowdCoin < totalCrowdCoin.mul(40).div(100) ){
       crowState = 3;

    } else if (havedCrowdCoin < totalCrowdCoin.mul(50).div(100) ){
       crowState = 4;
    }
      
    if (havedCrowdCoin >= totalCrowdCoin) {
       finishCrowdCoin = true;
  }
 }

function calculateCrowdAmount (uint _price) internal view returns (uint _crow) {
        
    if (crowState == 0) {
      return _price.mul(50000);
    }
    
     else if (crowState == 1) {
      return _price.mul(30000);
    
    } else if (crowState == 2) {
      return  _price.mul(20000);

    } else if (crowState == 3) {
     return  _price.mul(15000);

    } else if (crowState == 4) {
     return  _price.mul(10000);
    }

    return 0;
  }

}
/**
 * Define interface for distrible the token 
 */
function distributeToFound(address receiver, uint amount) onlyOwner() public  returns (uint actual){ 
  
   require((amount+havedDistFoundCoin) < totalFoundCoin);
  
   balances[owner] = balances[owner].sub(amount);
   balances[receiver] = balances[receiver].plus(amount);
   havedDistFoundCoin = havedDistFoundCoin.plus(amount);

   addFound(receiver);

   // This will make the mint transaction apper in EtherScan.io
   // We can remove this after there is a standardized minting event
   emit Transfer(0, receiver, amount);
   
   return amount;
}

/**发token给基金会*/