contract GoolaToken is StandardERC20Token, Owned,GoolaStop {



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

    uint256 constant public airdropSupply = 60 * 10**8 * GOOLA_UNIT;           
    uint256 constant public earlyInitProjectSupply = 10 * 10**8 * GOOLA_UNIT;  
    uint256 constant public teamSupply = 15 * 10**8 * GOOLA_UNIT;         
    uint256 constant public ecosystemSupply = 15 * 10**8 * GOOLA_UNIT;   
    
    uint256  public tokensReleasedToTeam = 0;
    uint256  public tokensReleasedToEcosystem = 0; 
    uint256  public currentSupply = 0;  
    
    address public goolaTeamAddress;     
    address public ecosystemAddress;
    address public backupAddress;

    uint256 internal createTime = 1527730299;             
    uint256 internal hasAirdrop = 0;
    uint256 internal hasReleaseForEarlyInit = 0;
    uint256 internal teamTranchesReleased = 0; 
    uint256 internal ecosystemTranchesReleased = 0;  
    uint256 internal maxTranches = 16;       

    function GoolaToken( address _ecosystemAddress, address _backupAddress, address _goolaTeamAddress)
    StandardERC20Token("Goola token", "GOOLA", 18) public
     {
        goolaTeamAddress = _goolaTeamAddress;
        ecosystemAddress = _ecosystemAddress;
        backupAddress = _backupAddress;
        createTime = now;
    }

    function transfer(address _to, uint256 _value) public stoppable returns (bool success) {
        return super.transfer(_to, _value);
    }


    function transferFrom(address _from, address _to, uint256 _value) public stoppable returns (bool success) {
            return super.transferFrom(_from, _to, _value);
    }
    
    function withdrawERC20TokenTo(IERC20Token _token, address _to, uint256 _amount)
        public
        ownerOnly
        validAddress(_token)
        validAddress(_to)
        notThis(_to)
    {
        assert(_token.transfer(_to, _amount));

    }
    
        
    function airdropBatchTransfer(address[] _to,uint256 _amountOfEach) public ownerOnly {
        require(_to.length > 0 && _amountOfEach > 0 && _to.length * _amountOfEach <=  (airdropSupply - hasAirdrop) && (currentSupply + (_to.length * _amountOfEach)) <= totalSupply && _to.length < 100000);
        for(uint16 i = 0; i < _to.length ;i++){
         balanceOf[_to[i]] = safeAdd(balanceOf[_to[i]], _amountOfEach);
          Transfer(0x0, _to[i], _amountOfEach);
        }
            currentSupply += (_to.length * _amountOfEach);
            hasAirdrop = safeAdd(hasAirdrop, _to.length * _amountOfEach);
    }
    
  function releaseForEarlyInit(address[] _to,uint256 _amountOfEach) public ownerOnly {
        require(_to.length > 0 && _amountOfEach > 0 && _to.length * _amountOfEach <=  (earlyInitProjectSupply - hasReleaseForEarlyInit) && (currentSupply + (_to.length * _amountOfEach)) <= totalSupply && _to.length < 100000);
        for(uint16 i = 0; i < _to.length ;i++){
          balanceOf[_to[i]] = safeAdd(balanceOf[_to[i]], _amountOfEach);
          Transfer(0x0, _to[i], _amountOfEach);
        }
            currentSupply += (_to.length * _amountOfEach);
            hasReleaseForEarlyInit = safeAdd(hasReleaseForEarlyInit, _to.length * _amountOfEach);
    }


    /**
        @dev Release one  tranche of the ecosystemSupply allocation to Goola ecosystem,6.25% every tranche.About 4 years ecosystemSupply release over.
       
        @return true if successful, throws if not
    */
    function releaseForEcosystem()   public ownerOnly  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 Goola team,6.25% every tranche.About 4 years Goola team will get teamSupply Tokens.
       
        @return true if successful, throws if not
    */
    function releaseForGoolaTeam()   public ownerOnly  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[goolaTeamAddress] = safeAdd(balanceOf[goolaTeamAddress], allocAmount);
            currentSupply += allocAmount;
            tokensReleasedToTeam = safeAdd(tokensReleasedToTeam, allocAmount);
            Transfer(0x0, goolaTeamAddress, allocAmount);
            return true;
        }
        revert();
    }
    
    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 releaseForGoolaTeam()   public ownerOnly  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[goolaTeamAddress] = safeAdd(balanceOf[goolaTeamAddress], allocAmount);
            currentSupply += allocAmount;
            tokensReleasedToTeam = safeAdd(tokensReleasedToTeam, allocAmount);
            Transfer(0x0, goolaTeamAddress, allocAmount);
            return true;
        }
        revert();
    }
/**
 @dev Release one  tranche of the teamSupply allocation to Goola team,6.25% every tranche.About 4 years Goola team will get teamSupply Tokens.
 
 @return true if successful, throws if not
 */