contract dHealthTokenSale is dHealthEtherDistributor, ERC223Receiver {
	using SafeMath for uint256;

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

	// amount of token to be sold on sale
	uint256 public maxTokenForSale = 180000000 * 1E18;

	// timestamp when phase 1 starts
	uint256 public phase1StartingAt = 1516924800; // Friday, 26 January 2018 00:00:00
	uint256 public phase1EndingAt = 1518134399; // Thursday, 8 February 2018 23:59:59
	uint256 public phase1MaxTokenForSale = maxTokenForSale * 1 / 3;
	uint256 public phase1TokenPriceInEth = 0.0005 ether;
	uint256 public phase1TokenSold = 0;

	// timestamp when phase 2 starts
	uint256 public phase2StartingAt = 1518134400; // Friday, 9 February 2018 00:00:00
	uint256 public phase2EndingAt = 1519343999; // Thursday, 22 February 2018 23:59:59
	uint256 public phase2MaxTokenForSale = maxTokenForSale * 2 / 3;
	uint256 public phase2TokenPriceInEth = 0.000606060606 ether;
	uint256 public phase2TokenSold = 0;

	// timestamp when phase 3 starts
	uint256 public phase3StartingAt = 1519344000; // Friday, 23 February 2018 00:00:00
	uint256 public phase3EndingAt = 1520553599; // Thursday, 8 March 2018 23:59:59
	uint256 public phase3MaxTokenForSale = maxTokenForSale;
	uint256 public phase3TokenPriceInEth = 0.000769230769 ether;
	uint256 public phase3TokenSold = 0;

	// contract timeout to initiate left funds and token transfer
	uint256 public contractTimeout = 1520553600; // Friday, 9 March 2018 00:00:00

	// growth contract address
	address public growthContract;

	// maximum ether invested per transaction
	uint256 public maxEthPerTransaction = 1000 ether;

	// minimum ether invested per transaction
	uint256 public minEthPerTransaction = 0.01 ether;

	// amount of token sold so far
	uint256 public totalTokenSold;

	// amount of ether raised in sale
	uint256 public totalEtherRaised;

	// ether raised per wallet
	mapping(address => uint256) public etherRaisedPerWallet;

	// is contract close and ended
	bool public isClose = false;

	// is contract paused
	bool public isPaused = false;

	// token purchsae event
	event TokenPurchase(address indexed _purchaser, address indexed _beneficiary, uint256 _value, uint256 _amount, uint256 _timestamp);

	// manual transfer by admin for external purchase
	event TransferManual(address indexed _from, address indexed _to, uint256 _value, string _message);

	/**
	* @dev Constructor that initializes token contract with token address in parameter
	*/
	function dHealthTokenSale(address _token, address _projectContract, address _technologyContract, address _founderContract, address _growthContract)
		dHealthEtherDistributor(_projectContract, _technologyContract, _founderContract)
		public {
		// set token
		token = dHealthToken(_token);

		// set growth contract address
		growthContract = _growthContract;
	}

	/**
	 * @dev Function that validates if the purchase is valid by verifying the parameters
	 *
	 * @param value Amount of ethers sent
	 * @param amount Total number of tokens user is trying to buy.
	 *
	 * @return checks various conditions and returns the bool result indicating validity.
	 */
	function validate(uint256 value, uint256 amount) internal constant returns (bool) {
		// check if timestamp and amount is falling in the range
		bool validTimestamp = false;
		bool validAmount = false;

		// check if phase 1 is running	
		if(phase1StartingAt <= getBlockTime() && getBlockTime() <= phase1EndingAt) {
			// check if tokens is falling in timerange
			validTimestamp = true;

			// check if token amount is falling in limit
			validAmount = phase1MaxTokenForSale.sub(totalTokenSold) >= amount;
		}

		// check if phase 2 is running	
		if(phase2StartingAt <= getBlockTime() && getBlockTime() <= phase2EndingAt) {
			// check if tokens is falling in timerange
			validTimestamp = true;

			// check if token amount is falling in limit
			validAmount = phase2MaxTokenForSale.sub(totalTokenSold) >= amount;
		}

		// check if phase 3 is running	
		if(phase3StartingAt <= getBlockTime() && getBlockTime() <= phase3EndingAt) {
			// check if tokens is falling in timerange
			validTimestamp = true;

			// check if token amount is falling in limit
			validAmount = phase3MaxTokenForSale.sub(totalTokenSold) >= amount;
		}

		// check if value of the ether is valid
		bool validValue = value != 0;

		// check if the tokens available in contract for sale
		bool validToken = amount != 0;

		// validate if all conditions are met
		return validTimestamp && validAmount && validValue && validToken && !isClose && !isPaused;
	}

	function calculate(uint256 value) internal constant returns (uint256) {
		uint256 amount = 0;
			
		// check if phase 1 is running	
		if(phase1StartingAt <= getBlockTime() && getBlockTime() <= phase1EndingAt) {
			// calculate the amount of tokens
			amount = value.mul(1E18).div(phase1TokenPriceInEth);
		}

		// check if phase 2 is running	
		if(phase2StartingAt <= getBlockTime() && getBlockTime() <= phase2EndingAt) {
			// calculate the amount of tokens
			amount = value.mul(1E18).div(phase2TokenPriceInEth);
		}

		// check if phase 3 is running	
		if(phase3StartingAt <= getBlockTime() && getBlockTime() <= phase3EndingAt) {
			// calculate the amount of tokens
			amount = value.mul(1E18).div(phase3TokenPriceInEth);
		}

		return amount;
	}

	function update(uint256 value, uint256 amount) internal returns (bool) {

		// update the state to log the sold tokens and raised ethers.
		totalTokenSold = totalTokenSold.add(amount);
		totalEtherRaised = totalEtherRaised.add(value);
		etherRaisedPerWallet[msg.sender] = etherRaisedPerWallet[msg.sender].add(value);

		// check if phase 1 is running	
		if(phase1StartingAt <= getBlockTime() && getBlockTime() <= phase1EndingAt) {
			// add tokens to phase1 counts
			phase1TokenSold = phase1TokenSold.add(amount);
		}

		// check if phase 2 is running	
		if(phase2StartingAt <= getBlockTime() && getBlockTime() <= phase2EndingAt) {
			// add tokens to phase2 counts
			phase2TokenSold = phase2TokenSold.add(amount);
		}

		// check if phase 3 is running	
		if(phase3StartingAt <= getBlockTime() && getBlockTime() <= phase3EndingAt) {
			// add tokens to phase3 counts
			phase3TokenSold = phase3TokenSold.add(amount);
		}
	}

	/**
	 * @dev Default fallback method which will be called when any ethers are sent to contract
	 */
	function() public payable {
		buy(msg.sender);
	}

	/**
	 * @dev Function that is called either externally or by default payable method
	 *
	 * @param beneficiary who should receive tokens
	 */
	function buy(address beneficiary) public payable {
		require(beneficiary != address(0));

		// amount of ethers sent
		uint256 value = msg.value;

		// throw error if not enough ethers sent
		require(value >= minEthPerTransaction);

		// refund the extra ethers if sent more than allowed
		if(value > maxEthPerTransaction) {
			// more ethers are sent so refund extra
			msg.sender.transfer(value.sub(maxEthPerTransaction));
			value = maxEthPerTransaction;
		}
		
		// calculate tokens
		uint256 tokens = calculate(value);

		// validate the purchase
		require(validate(value , tokens));

		// update current state 
		update(value , tokens);
		
		// transfer tokens from contract balance to beneficiary account. calling ERC223 method
		bytes memory empty;
		token.transfer(beneficiary, tokens, empty);
		
		// log event for token purchase
		TokenPurchase(msg.sender, beneficiary, value, tokens, now);
	}

	/**
	* @dev transmit token for a specified address. 
	* This is owner only method and should be called using web3.js if someone is trying to buy token using bitcoin or any other altcoin.
	* 
	* @param _to The address to transmit to.
	* @param _value The amount to be transferred.
	* @param _message message to log after transfer.
	*/
	function transferManual(address _to, uint256 _value, string _message) onlyOwner public returns (bool) {
		require(_to != address(0));

		// transfer tokens manually from contract balance
		token.transfer(_to , _value);
		TransferManual(msg.sender, _to, _value, _message);
		return true;
	}

	/**
	* @dev sendToGrowthContract  
	* This will send remaining tokens to growth contract
	*/	
	function sendToGrowthContract() onlyOwner public {
		require(contractTimeout <= getBlockTime());

		// send remaining tokens to growth contract.
		uint256 tokens = token.balanceOf(this); 
		bytes memory empty;
		token.transfer(growthContract, tokens, empty);
	}

	/**
	* @dev sendToVestingContract  
	* This will transfer any available ethers to vesting contracts
	*/	
	function sendToVestingContract() onlyOwner public {
		// distribute funds 
		distribute();
	}

	/**
	* @dev withdraw funds and tokens 
	* This will send remaining token balance to growth contract
	* This will distribute available funds across team members
	*/	
	function withdraw() onlyOwner public {
		require(contractTimeout <= getBlockTime());

		// send remaining tokens to growth contract.
		uint256 tokens = token.balanceOf(this); 
		bytes memory empty;
		token.transfer(growthContract, tokens, empty);

		// distribute funds 
		distribute();
	}

	/**
	* @dev close contract 
	* This will mark contract as closed
	*/	
	function close() onlyOwner public {
		// mark the flag to indicate closure of the contract
		isClose = true;
	}

	/**
	* @dev pause contract 
	* This will mark contract as paused
	*/	
	function pause() onlyOwner public {
		// mark the flag to indicate pause of the contract
		isPaused = true;
	}

	/**
	* @dev resume contract 
	* This will mark contract as resumed
	*/	
	function resume() onlyOwner public {
		// mark the flag to indicate resume of the contract
		isPaused = false;
	}
}
/**
 * @title dHealthTokenSale
 * @dev This is ICO Contract. 
 * This class accepts the token address as argument to talk with contract.
 * Once contract is deployed, funds are transferred to ICO smart contract address and then distributed with investor.
 * Sending funds to this ensures that no more than desired tokens are sold.
 */
function validate(uint256 value, uint256 amount) internal constant returns (bool) {
	// check if timestamp and amount is falling in the range
	bool validTimestamp = false;
	bool validAmount = false;

	// check if phase 1 is running	
	if(phase1StartingAt <= getBlockTime() && getBlockTime() <= phase1EndingAt) {
		// check if tokens is falling in timerange
		validTimestamp = true;

		// check if token amount is falling in limit
		validAmount = phase1MaxTokenForSale.sub(totalTokenSold) >= amount;
	}

	// check if phase 2 is running	
	if(phase2StartingAt <= getBlockTime() && getBlockTime() <= phase2EndingAt) {
		// check if tokens is falling in timerange
		validTimestamp = true;

		// check if token amount is falling in limit
		validAmount = phase2MaxTokenForSale.sub(totalTokenSold) >= amount;
	}

	// check if phase 3 is running	
	if(phase3StartingAt <= getBlockTime() && getBlockTime() <= phase3EndingAt) {
		// check if tokens is falling in timerange
		validTimestamp = true;

		// check if token amount is falling in limit
		validAmount = phase3MaxTokenForSale.sub(totalTokenSold) >= amount;
	}

	// check if value of the ether is valid
	bool validValue = value != 0;

	// check if the tokens available in contract for sale
	bool validToken = amount != 0;

	// validate if all conditions are met
	return validTimestamp && validAmount && validValue && validToken && !isClose && !isPaused;
}

/**
 	 * @dev Function that validates if the purchase is valid by verifying the parameters
 	 *
 	 * @param value Amount of ethers sent
 	 * @param amount Total number of tokens user is trying to buy.
 	 *
 	 * @return checks various conditions and returns the bool result indicating validity.
 	 */