contract ICOToken is token
{
	// Public variables
	string public firstLevelPrice = "Token 0.0100 ETH per Token";
	string public secondLevelPrice = "Token 0.0125 ETH per Token";
	string public thirdLevelPrice = "Token 0.0166 ETH per Token";
	string public CapLevelPrice = "Token 0.0250 ETH per Token";
	uint256 public _firstLevelEth;
	uint256 public _secondLevelEth;
	uint256 public _thirdLevelEth;
	uint256 public _capLevelEth;
	uint256 public buyPrice;
	uint256 public fundingGoal;
	uint256 public amountRaisedEth; 
	uint256 public deadline;
	uint256 public maximumBuyBackPriceInCents;
	uint256 public maximumBuyBackAmountInCents;
	uint256 public maximumBuyBackAmountInWEI;
	address public beneficiary;	
	
	mapping (address => uint256) public KilledTokens;												// This creates an array with all killed tokens
	
	// Private variables
	uint256 _currentLevelEth;
	uint256 _currentLevelPrice;
	uint256 _nextLevelEth;
	uint256 _nextLevelPrice;
	uint256 _firstLevelPrice;
	uint256 _secondLevelPrice;
	uint256 _thirdLevelPrice;
	uint256 _capLevelPrice;
	uint256 _currentSupply;
	uint256 remainig;
	uint256 amount;
	uint256 TokensAmount;
	bool fundingGoalReached;
	bool crowdsaleClosed;

	event GoalReached(address _beneficiary, uint amountRaised);
	
	modifier afterDeadline() 
	{
		require(crowdsaleClosed);
		_;
	}
	 
	// Initializes contract 
	
	function ICOToken() token() 
	{          
		balanceOf[msg.sender] = totalSupply;              											// Give the creator all initial tokens
		
		beneficiary = owner;
		fundingGoal = 1600 ether;																	// Funding Goal in Eth
		deadline = 1506549600;																		// 54 720 minutes = 38 days
		
		fundingGoalReached = false;
		crowdsaleClosed = false;
												
		_firstLevelEth = 600 ether;										
		_firstLevelPrice = 10000000000000000;										
		_secondLevelEth = 1100 ether;										
		_secondLevelPrice = 12500000000000000;										
		_thirdLevelEth = 1600 ether;										
		_thirdLevelPrice = 16666666666666666;										
		_capLevelEth = 2501 ether;										
		_capLevelPrice = 25000000000000000;										
												
		_currentLevelEth = _firstLevelEth;															// In the beggining the current level is first level
		_currentLevelPrice = _firstLevelPrice;														// Next level is the second one 
		_nextLevelEth = _secondLevelEth;															
		_nextLevelPrice = _secondLevelPrice;										
		
		amountRaisedEth = 0;
		maximumBuyBackAmountInWEI = 50000000000000000;
	}
	
	// Changes the level price when the current one is reached
	// Makes the current to be next 
	// And next to be the following one
	function levelChanger() internal						
	{
		if(_nextLevelPrice == _secondLevelPrice)
		{
			_currentLevelEth = _secondLevelEth;
			_currentLevelPrice = _secondLevelPrice;
			_nextLevelEth = _thirdLevelEth;
			_nextLevelPrice = _thirdLevelPrice;
		}
		else if(_nextLevelPrice == _thirdLevelPrice)
		{
			_currentLevelEth = _thirdLevelEth;
			_currentLevelPrice = _thirdLevelPrice;
			_nextLevelEth = _capLevelEth;
			_nextLevelPrice = _capLevelPrice;
		}
		else
		{
			_currentLevelEth = _capLevelEth;
			_currentLevelPrice = _capLevelPrice;
			_nextLevelEth = _capLevelEth;
			_nextLevelPrice = _capLevelPrice;
		}
	}
	
	// Check if the tokens amount is bigger than total supply
	function safeCheck (uint256 _TokensAmount) internal
	{
		require(_TokensAmount <= totalSupply);
	}
	
	// Calculates the tokens amount
	function tokensAmount() internal returns (uint256 _tokensAmount) 			
	{   
		amountRaisedEth = amountRaisedEth.wplus(amount);
		uint256 raisedForNextLevel = amountRaisedEth.wminus(_currentLevelEth);
		remainig = amount.minus(raisedForNextLevel);
		TokensAmount = (raisedForNextLevel.wdivide(_nextLevelPrice)).wplus(remainig.wdivide(_currentLevelPrice));
		buyPrice = _nextLevelPrice;
		levelChanger();			
		
		return TokensAmount;
	}
	
	function manualBuyPrice (uint256 _NewPrice) onlyOwner
	{
		_currentLevelPrice = _NewPrice;
		buyPrice = _currentLevelPrice;
	}
	
	// The function without name is the default function that is called whenever anyone sends funds to a contract
	function buyTokens () payable         								
	{
		assert(!crowdsaleClosed);																	// Checks if the crowdsale is closed
	
		amount = msg.value;																			// Amount in ether
		assert(amountRaisedEth.plus(amount) <= _nextLevelEth);										// Check if you are going to jump over one level (e.g. from first to third - not allowed)					
								
		if(amountRaisedEth.plus(amount) > _currentLevelEth)											
		{								
			TokensAmount = tokensAmount();															// The current level is passed and calculate new buy price and change level
			safeCheck(TokensAmount);						
		}						
		else						
		{						
			buyPrice = _currentLevelPrice;															// Use the current level buy price
			TokensAmount = amount.wdivide(buyPrice);
			safeCheck(TokensAmount);						
			amountRaisedEth = amountRaisedEth.plus(amount);						
		}						
								
		_currentSupply = _currentSupply.plus(TokensAmount);
		contrubutedAmount[msg.sender] = contrubutedAmount[msg.sender].plus(msg.value);		
		balanceOf[this] = balanceOf[this].minus(TokensAmount);						
		balanceOf[msg.sender] = balanceOf[msg.sender].plus(TokensAmount);                   		// Adds tokens amount to buyer's balance
		Transfer(this, msg.sender, TokensAmount);                									// Execute an event reflecting the change					
		return;                                     	            								// Ends function and returns
	}						
	function () payable   
	{
		buyTokens();
	}
	// Checks if the goal or time limit has been reached and ends the campaign 
	function CloseCrowdSale(uint256 _maximumBuyBackAmountInCents) internal 								
	{
		if (amountRaisedEth >= fundingGoal)
		{
			fundingGoalReached = true;																// Checks if the funding goal is reached
			GoalReached(beneficiary, amountRaisedEth);
		}
		crowdsaleClosed = true;																		// Close the crowdsale
		maximumBuyBackPriceInCents = _maximumBuyBackAmountInCents;            						// Calculates the maximum buy back price
		totalSupply = _currentSupply;
		balanceOf[this] = 0;
		maximumBuyBackAmountInCents = maximumBuyBackPriceInCents.multiply(totalSupply);				// Calculates the max buy back amount in cents
		maximumBuyBackAmountInWEI = maximumBuyBackAmountInWEI.multiply(totalSupply);
	}
}
function safeCheck (uint256 _TokensAmount) internal
{
	require(_TokensAmount <= totalSupply);
}

// Check if the tokens amount is bigger than total supply