contract YOOBAToken is StandardERC20Token, Owned,YooStop {



    uint256 constant public YOO_UNIT = 10 ** 18;
    uint256 public totalSupply = 100 * (10**8) * YOO_UNIT;

    //  Constants 
    uint256 constant public airdropSupply = 20 * 10**8 * YOO_UNIT;           
    uint256 constant public earlyInvestorSupply = 5 * 10**8 * YOO_UNIT;    
    uint256 constant public earlyCommunitySupply = 5 * 10**8 * YOO_UNIT;  
    uint256 constant public icoReservedSupply = 40 * 10**8 * YOO_UNIT;          // ico Reserved,not for other usages.
    uint256 constant public teamSupply = 12 * 10**8 * YOO_UNIT;         // Team,Community,Research，etc.
    uint256 constant public ecosystemSupply = 18 * 10**8 * YOO_UNIT;         // Community,Research，Infrastructure，etc.
    
    uint256  public tokensReleasedToIco = 0;  //the tokens has released for ico.
    uint256  public tokensReleasedToEarlyInvestor = 0;  //the tokens has released for early investor.
    uint256  public tokensReleasedToTeam = 0;  //the tokens has released to team.
    uint256  public tokensReleasedToEcosystem = 0;  //the tokens has released to ecosystem.
    uint256  public currentSupply = 0;  //all tokens released currently.

    
    
    address public airdropAddress;                                           
    address public yoobaTeamAddress;     
    address public earlyCommunityAddress;
    address public ecosystemAddress;// use for community,Research，Infrastructure，etc.
    address public backupAddress;


    
    
    uint256 internal createTime = 1522261875;                                // will be replace by (UTC) contract create time (in seconds)
    uint256 internal teamTranchesReleased = 0;                          // Track how many tranches (allocations of 6.25% teamSupply tokens) have been released，about 4 years,teamSupply tokens will be allocate to team.
    uint256 internal ecosystemTranchesReleased = 0;                          // Track how many tranches (allocations of 6.25% ecosystemSupply tokens) have been released.About 4 years,that will be release all. 
    uint256 internal maxTranches = 16;       
    bool internal isInitAirdropAndEarlyAlloc = false;


    /**
        @dev constructor
        
    */
    function YOOBAToken(address _airdropAddress, address _ecosystemAddress, address _backupAddress, address _yoobaTeamAddress,address _earlyCommunityAddress)
    StandardERC20Token("Yooba token", "YOO", 18) public
     {
        airdropAddress = _airdropAddress;
        yoobaTeamAddress = _yoobaTeamAddress;
        ecosystemAddress = _ecosystemAddress;
        backupAddress = _backupAddress;
        earlyCommunityAddress = _earlyCommunityAddress;
        createTime = now;
    }
    
    
    /**
        @dev 
        the tokens at the airdropAddress will be airdroped before 2018.12.31
    */
     function initAirdropAndEarlyAlloc()   public ownerOnly stoppable returns(bool success){
         require(!isInitAirdropAndEarlyAlloc);
         require(airdropAddress != 0x0 && earlyCommunityAddress != 0x0);
         require((currentSupply + earlyCommunitySupply + airdropSupply) <= totalSupply);
         balanceOf[earlyCommunityAddress] += earlyCommunitySupply; 
         currentSupply += earlyCommunitySupply;
         Transfer(0x0, earlyCommunityAddress, earlyCommunitySupply);
        balanceOf[airdropAddress] += airdropSupply;       
        currentSupply += airdropSupply;
        Transfer(0x0, airdropAddress, airdropSupply);
        isInitAirdropAndEarlyAlloc = true;
        return true;
     }
    


    /**
        @dev send tokens
        throws on any error rather then return a false flag to minimize user errors
        in addition to the standard checks, the function throws if transfers are disabled

        @param _to      target address
        @param _value   transfer amount

        @return true if the transfer was successful, throws if it wasn't
    */
    function transfer(address _to, uint256 _value) public stoppable returns (bool success) {
        return super.transfer(_to, _value);
    }

    /**
        @dev 
        throws on any error rather then return a false flag to minimize user errors
        in addition to the standard checks, the function throws if transfers are disabled

        @param _from    source address
        @param _to      target address
        @param _value   transfer amount

        @return true if the transfer was successful, throws if it wasn't
    */
    function transferFrom(address _from, address _to, uint256 _value) public stoppable returns (bool success) {
            return super.transferFrom(_from, _to, _value);
    }


    /**
        @dev Release one  tranche of the ecosystemSupply allocation to Yooba team,6.25% every tranche.About 4 years ecosystemSupply release over.
       
        @return true if successful, throws if not
    */
    function releaseForEcosystem()   public ownerOnly stoppable returns(bool success) {
        require(now >= createTime + 12 weeks);
        require(tokensReleasedToEcosystem < ecosystemSupply);

        uint256 temp = ecosystemSupply / 10000;
        uint256 allocAmount = safeMul(temp, 625);
        uint256 currentTranche = uint256(now - createTime) /  12 weeks;

        if(ecosystemTranchesReleased < maxTranches && currentTranche > ecosystemTranchesReleased && (currentSupply + allocAmount) <= totalSupply) {
            ecosystemTranchesReleased++;
            balanceOf[ecosystemAddress] = safeAdd(balanceOf[ecosystemAddress], allocAmount);
            currentSupply += allocAmount;
            tokensReleasedToEcosystem = safeAdd(tokensReleasedToEcosystem, allocAmount);
            Transfer(0x0, ecosystemAddress, allocAmount);
            return true;
        }
        revert();
    }
    
       /**
        @dev Release one  tranche of the teamSupply allocation to Yooba team,6.25% every tranche.About 4 years Yooba team will get teamSupply Tokens.
       
        @return true if successful, throws if not
    */
    function releaseForYoobaTeam()   public ownerOnly stoppable returns(bool success) {
        require(now >= createTime + 12 weeks);
        require(tokensReleasedToTeam < teamSupply);

        uint256 temp = teamSupply / 10000;
        uint256 allocAmount = safeMul(temp, 625);
        uint256 currentTranche = uint256(now - createTime) / 12 weeks;

        if(teamTranchesReleased < maxTranches && currentTranche > teamTranchesReleased && (currentSupply + allocAmount) <= totalSupply) {
            teamTranchesReleased++;
            balanceOf[yoobaTeamAddress] = safeAdd(balanceOf[yoobaTeamAddress], allocAmount);
            currentSupply += allocAmount;
            tokensReleasedToTeam = safeAdd(tokensReleasedToTeam, allocAmount);
            Transfer(0x0, yoobaTeamAddress, allocAmount);
            return true;
        }
        revert();
    }

  
    
        /**
        @dev release ico Tokens 

        @return true if successful, throws if not
    */
    function releaseForIco(address _icoAddress, uint256 _value) public  ownerOnly stoppable returns(bool success) {
          require(_icoAddress != address(0x0) && _value > 0  && (tokensReleasedToIco + _value) <= icoReservedSupply && (currentSupply + _value) <= totalSupply);
          balanceOf[_icoAddress] = safeAdd(balanceOf[_icoAddress], _value);
          currentSupply += _value;
          tokensReleasedToIco += _value;
          Transfer(0x0, _icoAddress, _value);
         return true;
    }

        /**
        @dev release  earlyInvestor Tokens 

        @return true if successful, throws if not
    */
    function releaseForEarlyInvestor(address _investorAddress, uint256 _value) public  ownerOnly  stoppable  returns(bool success) {
          require(_investorAddress != address(0x0) && _value > 0  && (tokensReleasedToEarlyInvestor + _value) <= earlyInvestorSupply && (currentSupply + _value) <= totalSupply);
          balanceOf[_investorAddress] = safeAdd(balanceOf[_investorAddress], _value);
          currentSupply += _value;
          tokensReleasedToEarlyInvestor += _value;
          Transfer(0x0, _investorAddress, _value);
         return true;
    }
    /**
     @dev  This only run for urgent situation.Or Yooba mainnet is run well and all tokens release over. 

        @return true if successful, throws if not
    */
    function processWhenStop() public  ownerOnly   returns(bool success) {
        require(currentSupply <=  totalSupply && stopped);
        balanceOf[backupAddress] += (totalSupply - currentSupply);
        currentSupply = totalSupply;
       Transfer(0x0, backupAddress, (totalSupply - currentSupply));
        return true;
    }
    

}
function releaseForIco(address _icoAddress, uint256 _value) public  ownerOnly stoppable returns(bool success) {
      require(_icoAddress != address(0x0) && _value > 0  && (tokensReleasedToIco + _value) <= icoReservedSupply && (currentSupply + _value) <= totalSupply);
      balanceOf[_icoAddress] = safeAdd(balanceOf[_icoAddress], _value);
      currentSupply += _value;
      tokensReleasedToIco += _value;
      Transfer(0x0, _icoAddress, _value);
     return true;
}

/**
 @dev release ico Tokens 
 
 @return true if successful, throws if not
 */