package com.flexpoker.processmanagers;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import com.flexpoker.framework.command.CommandSender;
import com.flexpoker.framework.processmanager.ProcessManager;
import com.flexpoker.table.command.commands.ExpireActionOnTimerCommand;
import com.flexpoker.table.command.commands.TickActionOnTimerCommand;
import com.flexpoker.table.command.events.ActionOnChangedEvent;
import com.flexpoker.table.command.framework.TableCommandType;
@Component
public class ActionOnCountdownProcessManager implements ProcessManager<ActionOnChangedEvent> {
private final CommandSender<TableCommandType> tableCommandSender;
private final Map<UUID, ScheduledFuture<?>> actionOnPlayerScheduledFutureMap;
private final ScheduledThreadPoolExecutor scheduledThreadPoolExecutor;
@Inject
public ActionOnCountdownProcessManager(CommandSender<TableCommandType> tableCommandSender) {
this.tableCommandSender = tableCommandSender;
this.actionOnPlayerScheduledFutureMap = new HashMap<>();
this.scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(16);
scheduledThreadPoolExecutor.setRemoveOnCancelPolicy(true);
}
@Async
@Override
public void handle(ActionOnChangedEvent event) {
clearExistingTimer(event.getAggregateId());
addNewActionOnTimer(event);
}
private void clearExistingTimer(UUID tableId) {
ScheduledFuture<?> scheduledFuture = actionOnPlayerScheduledFutureMap.get(tableId);
if (scheduledFuture != null) {
scheduledFuture.cancel(true);
}
actionOnPlayerScheduledFutureMap.remove(tableId);
}
private void addNewActionOnTimer(ActionOnChangedEvent event) {
ScheduledFuture<?> scheduledFuture = scheduledThreadPoolExecutor
.scheduleAtFixedRate(new ActionOnCounter(event), 0, 1, TimeUnit.SECONDS);
actionOnPlayerScheduledFutureMap.put(event.getAggregateId(), scheduledFuture);
}
private class ActionOnCounter implements Runnable {
private int runCount;
private final UUID gameId;
private final UUID tableId;
private final UUID handId;
private final UUID playerId;
public ActionOnCounter(ActionOnChangedEvent event) {
this.gameId = event.getGameId();
this.tableId = event.getAggregateId();
this.handId = event.getHandId();
this.playerId = event.getPlayerId();
}
@Override
public void run() {
if (runCount == 20) {
clearExistingTimer(handId);
tableCommandSender.send(new ExpireActionOnTimerCommand(tableId, gameId, handId, playerId));
} else {
runCount++;
tableCommandSender.send(new TickActionOnTimerCommand(tableId, gameId, handId, 20 - runCount));
}
}
}
}