package com.akkademy.clientactor;

import akka.actor.AbstractActorWithStash;
import akka.actor.ActorSelection;
import akka.japi.pf.ReceiveBuilder;
import com.akkademy.messages.Connected;
import com.akkademy.messages.Request;
import scala.PartialFunction;
import scala.runtime.BoxedUnit;

/**
 * Use mailbox with stash-capacity
 * or build some sort of timeout to avoid memory leak.
 */

public class HotswapClientActor extends AbstractActorWithStash {
    private ActorSelection remoteDb;

    private PartialFunction<Object, BoxedUnit> disconnected;
    private PartialFunction<Object, BoxedUnit> online;

    public HotswapClientActor(String dbPath) {
        remoteDb = context().actorSelection(dbPath);

        disconnected = ReceiveBuilder.
                match(Request.class, x -> { //can't handle until we know remote system is responding
                    remoteDb.tell(new Connected(), self()); //see if the remote actor is up
                    stash(); //stash message for later
                }).
                match(Connected.class, x -> { // Okay to start processing messages.
                    context().become(online);
                    unstash();
                }).build();

        online = ReceiveBuilder.
                        match(Request.class, x -> {
                            remoteDb.forward(x, context()); //forward instead of tell to preserve sender
                        }).
                        build();

        receive(disconnected); //initial state.
    }
}


/**
 * package com.akkademy
 * <p>
 * import akka.actor.{Actor, Stash}
 * import com.akkademy.messages.{Connected, Request}
 * <p>
 * class HotswapClientActor(address: String) extends Actor with Stash {
 * private val remoteDb = context.system.actorSelection(address)
 * <p>
 * override def receive = {
 * case x: Request =>  //can't handle until we know remote system is responding
 * remoteDb ! new Connected //see if the remote actor is up
 * stash() //stash message for later
 * case _: Connected => // Okay to start processing messages.
 * context.become(online)
 * }
 * <p>
 * def online: Receive = {
 * case x: Disconnected =>
 * context.unbecome()
 * case x: Request =>
 * remoteDb ! x
 * }
 * }
 * <p>
 * /**
 * Disconnect msg is unimplemented in this example.
 * Because we're not dealing w/ sockets directly,
 * we could instead implement an occasional ping/heartbeat that restarts
 * this Actor if the remote actor isn't responding.
 * After restarting, the actor will revert to the
 * default state and stash messages
 */

class Disconnected {
}

@@ -1511,720 +1511,8 @@
 %0A%7D%0A%0A
-%0A/**%0A * package com.akkademy%0A * %3Cp%3E%0A * import akka.actor.%7BActor, Stash%7D%0A * import com.akkademy.messages.%7BConnected, Request%7D%0A * %3Cp%3E%0A * class HotswapClientActor(address: String) extends Actor with Stash %7B%0A * private val remoteDb = context.system.actorSelection(address)%0A * %3Cp%3E%0A * override def receive = %7B%0A * case x: Request =%3E  //can't handle until we know remote system is responding%0A * remoteDb ! new Connected //see if the remote actor is up%0A * stash() //stash message for later%0A * case _: Connected =%3E // Okay to start processing messages.%0A * context.become(online)%0A * %7D%0A * %3Cp%3E%0A * def online: Receive = %7B%0A * case x: Disconnected =%3E%0A * context.unbecome()%0A * case x: Request =%3E%0A * remoteDb ! x%0A * %7D%0A * %7D%0A * %3Cp%3E%0A
  * /

remove commented code