package actors

import akka.actor.{Actor, ActorLogging, ActorRef, ActorSystem, Props}
import akka.event.LoggingReceive
import akka.pattern.ask
import akka.util.Timeout
import com.typesafe.scalalogging.LazyLogging

import scala.collection.mutable.ListBuffer
import scala.concurrent.Await
import scala.concurrent.duration.DurationInt

class LobbiesActor extends Actor with LazyLogging {

  implicit val timeout: Timeout = 1.second

  val lobbies: ListBuffer[String] = ListBuffer()

  def receive: Receive = LoggingReceive {
    case CreateLobby(hostName, deciderName) =>
      val hostActorRef = sender
      logger.info(s"Player ${hostActorRef.path.name} create lobby.")
      val lobbyActor = context.actorOf(Props(new LobbieActor(LobbyUser(hostName, hostActorRef), deciderName)),
        s"lobbyActor-${(math.random * 100000000L).toLong}")
      lobbyActor.tell(WatchLobby("watchIt"), hostActorRef)
    case JoinLobbyByActorName(lobbyName, userName) =>
      // get or create the StockActor for the symbol and forward this message
      val user = sender
      context.child(lobbyName) match {
        case Some(lobbyActor) => lobbyActor ! JoinLobbyAsPlayer(LobbyUser(userName, user))
        case None => logger.error(s"Can't watch lobby $lobbyName - lobby not exists")
      }
    case ObserveLobbyByActorName(lobbyName) =>
      val user = sender
      context.child(lobbyName) match {
        case Some(lobbyActor) => lobbyActor.tell(WatchLobby("watchIt"), user)
        case None => logger.error(s"Can't watch lobby $lobbyName - lobby not exists")
      }
    case watchLobby@WatchLobby(lobbyName) =>
      context.child(lobbyName) match {
        case Some(lobbyActor) => lobbyActor forward watchLobby
        case None => logger.error(s"Can't watch lobby $lobbyName - lobby not exists")
      }
    case UnWatchAllLobbies =>
      context.children.foreach(_.tell(LeaveLobby, sender))
    case GetAllLobbies =>
      sender ! context.children.toList.map(lobbyActor =>
        Await.result(lobbyActor ? InfoQuery, 1.second))

  }

}

case object GetAllLobbies

case class JoinLobbyByActorName(actorName: String, userName: String)

case class ObserveLobbyByActorName(actorName: String)

case object UnWatchAllLobbies

object LobbiesActor {
  implicit val actorSystem: ActorSystem = ActorSystem()
  val actor: ActorRef = actorSystem.actorOf(Props[LobbiesActor]())
}
