contract dHealthTokenGrowth is Ownable, ERC223Receiver, Timestamped {
	using SafeMath for uint256;

	// The token being sold, this holds reference to main token contract
	dHealthToken public token;

	// amount of token on hold
	uint256 public maxTokenForHold = 180000000 * 1E18;

	// exchanges wallet address
	address public exchangesWallet;
	uint256 public exchangesTokens = 45000000 * 1E18;
	uint256 public exchangesLockEndingAt = 1523750400; // Sunday, 15 April 2018 00:00:00
	bool public exchangesStatus = false;

	// countries wallet address
	address public countriesWallet;
	uint256 public countriesTokens = 45000000 * 1E18;
	uint256 public countriesLockEndingAt = 1525132800; // Tuesday, 1 May 2018 00:00:00
	bool public countriesStatus = false;

	// acquisitions wallet address
	address public acquisitionsWallet;
	uint256 public acquisitionsTokens = 45000000 * 1E18;
	uint256 public acquisitionsLockEndingAt = 1526342400; // Tuesday, 15 May 2018 00:00:00
	bool public acquisitionsStatus = false;

	// coindrops wallet address
	address public coindropsWallet;
	uint256 public coindropsTokens = 45000000 * 1E18;
	uint256 public coindropsLockEndingAt = 1527811200; // Friday, 1 June 2018 00:00:00
	bool public coindropsStatus = false;

	// contract timeout 
	uint256 public contractTimeout = 1555286400; // Monday, 15 April 2019 00:00:00

	/**
	* @dev Constructor that initializes vesting contract with contract addresses in parameter
	*/
	function dHealthTokenGrowth(address _token, address _exchangesWallet, address _countriesWallet, address _acquisitionsWallet, address _coindropsWallet) public {
		// set token
		token = dHealthToken(_token);

		// setup wallet addresses
		exchangesWallet = _exchangesWallet;
		countriesWallet = _countriesWallet;
		acquisitionsWallet = _acquisitionsWallet;
		coindropsWallet = _coindropsWallet;
	}

	/**
	* @dev Method called by anyone to withdraw funds to exchanges wallet after locking period
	*/
	function withdrawExchangesToken() public {
		// check if time has reached
		require(exchangesLockEndingAt <= getBlockTime());
		// ensure that tokens are not already transferred
		require(exchangesStatus == false);
		
		// transfer tokens to wallet and change status to prevent double transfer		
		bytes memory empty;
		token.transfer(exchangesWallet, exchangesTokens, empty);
		exchangesStatus = true;
	}

	/**
	* @dev Method called by anyone to withdraw funds to countries wallet after locking period
	*/
	function withdrawCountriesToken() public {
		// check if time has reached
		require(countriesLockEndingAt <= getBlockTime());
		// ensure that tokens are not already transferred
		require(countriesStatus == false);
		
		// transfer tokens to wallet and change status to prevent double transfer		
		bytes memory empty;
		token.transfer(countriesWallet, countriesTokens, empty);
		countriesStatus = true;
	}

	/**
	* @dev Method called by anyone to withdraw funds to acquisitions wallet after locking period
	*/
	function withdrawAcquisitionsToken() public {
		// check if time has reached
		require(acquisitionsLockEndingAt <= getBlockTime());
		// ensure that tokens are not already transferred
		require(acquisitionsStatus == false);
		
		// transfer tokens to wallet and change status to prevent double transfer		
		bytes memory empty;
		token.transfer(acquisitionsWallet, acquisitionsTokens, empty);
		acquisitionsStatus = true;
	}

	/**
	* @dev Method called by anyone to withdraw funds to coindrops wallet after locking period
	*/
	function withdrawCoindropsToken() public {
		// check if time has reached
		require(coindropsLockEndingAt <= getBlockTime());
		// ensure that tokens are not already transferred
		require(coindropsStatus == false);
		
		// transfer tokens to wallet and change status to prevent double transfer		
		bytes memory empty;
		token.transfer(coindropsWallet, coindropsTokens, empty);
		coindropsStatus = true;
	}

	/**
	* @dev Method called by owner of contract to withdraw all tokens after timeout has reached
	*/
	function withdraw() onlyOwner public {
		require(contractTimeout <= getBlockTime());
		
		// send remaining tokens back to owner.
		uint256 tokens = token.balanceOf(this); 
		bytes memory empty;
		token.transfer(owner, tokens, empty);
	}
}
/**
 * @title dHealthTokenGrowth
 * @dev This is token growth contract it receives tokens and holds it for certain period of time
 */
function dHealthTokenGrowth(address _token, address _exchangesWallet, address _countriesWallet, address _acquisitionsWallet, address _coindropsWallet) public {
	// set token
	token = dHealthToken(_token);

	// setup wallet addresses
	exchangesWallet = _exchangesWallet;
	countriesWallet = _countriesWallet;
	acquisitionsWallet = _acquisitionsWallet;
	coindropsWallet = _coindropsWallet;
}

/**
 	* @dev Constructor that initializes vesting contract with contract addresses in parameter
 	*/