package su.iota.backend.game;

import co.paralleluniverse.actors.ActorRef;
import co.paralleluniverse.actors.BasicActor;
import co.paralleluniverse.actors.behaviors.RequestReplyHelper;
import co.paralleluniverse.fibers.SuspendExecution;
import com.esotericsoftware.minlog.Log;
import org.glassfish.hk2.api.PerLookup;
import org.jetbrains.annotations.Nullable;
import org.jvnet.hk2.annotations.Service;
import su.iota.backend.messages.IncomingMessage;
import su.iota.backend.messages.OutgoingMessage;
import su.iota.backend.messages.game.GameResultMessage;
import su.iota.backend.messages.game.PlayerActionMessage;
import su.iota.backend.messages.game.PlayerActionResultMessage;
import su.iota.backend.messages.internal.GameSessionInitMessage;
import su.iota.backend.models.UserProfile;

import javax.inject.Inject;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
@PerLookup
public final class GameSessionActor extends BasicActor<IncomingMessage, GameResultMessage> {

    @Inject
    GameMechanics gameMechanics;

    private Map<ActorRef<Object>, UserProfile> players;

    @Override
    protected GameResultMessage doRun() throws InterruptedException, SuspendExecution {
        //noinspection InfiniteLoopStatement
        while (true) {
            final IncomingMessage message = receive(3, TimeUnit.SECONDS);
            if (message instanceof GameSessionInitMessage) {
                final GameSessionInitMessage initMessage = ((GameSessionInitMessage) message);
                if (this.players != null) {
                    RequestReplyHelper.reply(initMessage, false);
                } else {
                    this.players = initMessage.getPlayers();
                    RequestReplyHelper.reply(initMessage, true);
                }
            } else if (message instanceof PlayerActionMessage) {
                handlePlayerActionMessage((PlayerActionMessage) message);
            }
            checkCodeSwap();
        }
    }

    private void handlePlayerActionMessage(PlayerActionMessage message) throws SuspendExecution {
        final PlayerActionMessage actionMessage = (PlayerActionMessage) message;
        //noinspection unchecked
        final ActorRef<Object> sender = (ActorRef<Object>) actionMessage.getFrom();
        Log.info("Player " + actionMessage.getFrom() + " is ready: " + actionMessage.getReady());
        final PlayerActionResultMessage actionResultMessage = new PlayerActionResultMessage();
        actionResultMessage.setOk(true);
        actionResultMessage.setPayload(self().toString());
        sender.send(actionResultMessage);
    }

    @Override
    protected @Nullable IncomingMessage filterMessage(Object m) {
        if (players == null && !(m instanceof GameSessionInitMessage)) {
            return null;
        }
        return super.filterMessage(m);
    }

    //

}

@@ -867,16 +867,86 @@
 eUnit;%0A%0A
+import static su.iota.backend.misc.SuspendableUtils.rethrowConsumer;%0A%0A
 @Service
@@ -2142,198 +2142,343 @@
     
-final PlayerActionMessage actionMessage = (PlayerActionMessage) message;%0A        //noinspection unchecked%0A        final ActorRef%3CObject%3E sender = (ActorRef%3CObject%3E) actionMessage.getFrom
+//noinspection unchecked%0A        final ActorRef%3CObject%3E frontend = (ActorRef%3CObject%3E) message.getFrom();%0A        if (frontend == null) %7B%0A            throw new AssertionError();%0A        %7D%0A        final UserProfile userProfile = players.get(frontend);%0A        if (userProfile == null) %7B%0A            throw new AssertionError
 ();%0A
+        %7D%0A
     
@@ -2506,29 +2506,28 @@
 %22 + 
-actionMessage.getFrom
+userProfile.getLogin
 () +
@@ -2547,15 +2547,9 @@
 %22 + 
-actionM
+m
 essa
@@ -2560,24 +2560,95 @@
 etReady());%0A
+        players.entrySet().stream().forEach(rethrowConsumer(e -%3E %7B%0A    
         fina
@@ -2675,23 +2675,17 @@
 Message 
-actionR
+r
 esultMes
@@ -2724,39 +2724,37 @@
 sage();%0A        
-actionR
+    r
 esultMessage.set
@@ -2771,23 +2771,21 @@
         
-actionR
+    r
 esultMes
@@ -2804,67 +2804,155 @@
 oad(
+u
 se
-lf().toString());%0A        sender.send(actionResultMessage
+rProfile.getId() + %22 :: %22 + userProfile.getLogin() + %22 :: ready: %22 + message.getReady());%0A            e.getKey().send(resultMessage);%0A        %7D)
 );%0A 

Work on game session : some send-all payload