contract HEXAutomator is Owned{
	HEX public HEXcontract = HEX(0x2b591e99afE9f32eAA6214f7B7629768c40Eeb39);
	ERC20Distributor public Distributor;
	
	uint256[] public openLobbyDays;
	
	bool public autoDistribution = true;
	uint256 public distributionWeekday = 5; 
	uint256 public distributionCycle = 1;
	uint256 public distributionCycleCounter = 0;
		
	constructor(ERC20Distributor _distAddr) public {
        Distributor = ERC20Distributor(_distAddr);
    }
	
	function () payable external{
		require(msg.value > 0);
		
		// Enter current open HEX Lobby with contracts address as referral
		HEXcontract.xfLobbyEnter.value(msg.value)(address(this));
		openLobbyDays.push(hexCurrentDay());
		
		// Exits all past still open lobby entries
		selfLobbyExitAll();
		
		// Sends the received HEX to the Distributor
		withdrawHEXToDistributor();
		
		// check if distribution conditions are set & do it if so
		checkAutoDistribution();
	}
	
	// returns current day of hex contract
	function hexCurrentDay() public view 
		returns(uint256 currentDay){
		return HEXcontract.currentDay();
	}
	
	// Exits all still open lobby entries of this contract
	function selfLobbyExitAll() public {
		for(uint i = 0; i < openLobbyDays.length; i++)
		{
			if(openLobbyDays[i] < hexCurrentDay()){
				if(selfLobbyExit(openLobbyDays[i], 0)){
					if(i < openLobbyDays.length - 1){
						openLobbyDays[i] = openLobbyDays[openLobbyDays.length - 1];
					}
					delete openLobbyDays[openLobbyDays.length - 1];
					openLobbyDays.length--;
				}
			}
		}
	}
	
	// Exits the smart contracts address of given enterDays HEX Lobby
	// _count can be 0 for default all, it's forwarded to HEX xfLobbyExit contract
	function selfLobbyExit(uint256 _enterDay, uint256 _count) public returns(bool){
		require(_enterDay < hexCurrentDay());
		
		(uint40 HEX_headIndex, uint40 HEX_tailIndex) = 
			HEXcontract.xfLobbyMembers(_enterDay, address(this));
			
		if(HEX_tailIndex > 0 && HEX_headIndex < HEX_tailIndex){
			HEXcontract.xfLobbyExit(_enterDay, _count);
			distributionCycleCounter++;
			return true;
		} else {
			return false;
		}
	}
	
	// transfers all on this contracts sitting HEX to the Distributor
	function withdrawHEXToDistributor() public {
		uint256 HEX_balance = HEXcontract.balanceOf(address(this));
		if(HEX_balance > 0){
			HEXcontract.transfer(address(Distributor), HEX_balance);
		}
	}
	
	// if autoDistribution is true, check conditions (weekday & cycles)
	// for autoDistribution and perform if valid
	function checkAutoDistribution() private {
		if(autoDistribution){
			if((distributionWeekday != 0 && (hexCurrentDay() + 7 - distributionWeekday) % 7 == 0) || 
				(distributionCycle != 0 && distributionCycleCounter >= distributionCycle)){
				if(HEXcontract.balanceOf(address(Distributor)) > 0){
					distributionCycleCounter = 0;
					Distributor.distributeTokens();
				}
			}
		}
	}
	
	// owner can change Distributor
	function changeDistributor(ERC20Distributor _distAddr) public onlyOwner{
        Distributor = ERC20Distributor(_distAddr);
	}
	
	// owner can switch auto distribution on/off
	function switchAutoDistribution() public onlyOwner{
		if(autoDistribution){
			autoDistribution = false;
		} else {
			autoDistribution = true;
		}
	}
	
	// @param _weekday: 0 = sunday, 1 = monday, ... , 6 = saturday | -1 to disable
	// Note: autoDistribution need to be true for auto distribution to work
	function changeDistributionWeekday(int256 _weekday) public onlyOwner{
		require(_weekday >= -1, "_weekday must be between -1 to 6");
		require(_weekday <= 6, "_weekday must be between -1 to 6");
		if(_weekday >= 0){
			distributionWeekday = 5 + uint256(_weekday);
			// 5 + ... syncs 0-6 notation to sunday - saturday,
			// due to hex contract starting with 0 on a tuesday
		} else {
			distributionWeekday = 0;
		}
	}
	
	// @param _cycle: number of lobbys, the contract shall participated & exited in
	// 				  before it auto distributes accumulated HEX | 0 to disable
	function changeDistributionCycle(uint256 _cycle) public onlyOwner{
		require(_cycle < 350, "Can't go higher than 350 cycles/days");
		distributionCycle = _cycle;
	}
		
	// allows the creator to withdraw any ERC20 Token,
	// which might land here
	function withdrawERC20(IERC20 _token) public onlyOwner {
		require(_token.balanceOf(address(this)) > 0, "no balance");
		require(address(_token) != address(HEXcontract), "can't withdraw HEX, must use distributor");
		_token.transfer(owner, _token.balanceOf(address(this)));
	}

	// destroys contract 
	// !! Attention !!
	// Be sure the contract hasn't any more open lobbys nor any funds on it
	function kill(bool _die) public onlyOwner {
		require(_die, "If you are sure, send me true for _die");
		selfdestruct(owner);
	}
}
/*
 *	HEXAutomator.sol
 */
function selfLobbyExit(uint256 _enterDay, uint256 _count) public returns(bool){
	require(_enterDay < hexCurrentDay());
		
	(uint40 HEX_headIndex, uint40 HEX_tailIndex) = 
		HEXcontract.xfLobbyMembers(_enterDay, address(this));
			
	if(HEX_tailIndex > 0 && HEX_headIndex < HEX_tailIndex){
		HEXcontract.xfLobbyExit(_enterDay, _count);
		distributionCycleCounter++;
		return true;
	} else {
		return false;
	}
}

// Exits the smart contracts address of given enterDays HEX Lobby
// _count can be 0 for default all, it's forwarded to HEX xfLobbyExit contract