package wow.doge.mygame.game

import scala.concurrent.duration._

import akka.actor.typed.SupervisorStrategy
import akka.actor.typed.scaladsl.Behaviors
import wow.doge.mygame.game.TickGenerator.Send
import wow.doge.mygame.game.entities.GenericTimerActor
import wow.doge.mygame.subsystems.events.EventBus
import wow.doge.mygame.subsystems.events.EventsModule.GameEventBus
import wow.doge.mygame.subsystems.events.TickEvent
import wow.doge.mygame.subsystems.events.TickEvent.PhysicsTick

object GameAppActor {

  sealed trait Command
  case object Start extends Command
  case object Pause extends Command
  case object Stop extends Command

  case class Props(
      // app: SimpleAppExt,
      // akkaScheduler: Scheduler,
      // schedulers: Schedulers,
      // spawnProtocol: ActorRef[SpawnProtocol.Command],
      // loggerL: Logger[Task]
      tickEventBus: GameEventBus[TickEvent]
  ) {
    def behavior =
      Behaviors.setup[Command] { ctx =>
        ctx.log.info("Hello from GameAppActor")
        val renderTickGenerator =
          ctx.spawn(
            Behaviors
              .supervise(renderTickGeneratorBehavior)
              .onFailure[Exception](SupervisorStrategy.restart),
            "tickGeneratorActor"
          )

        val tickGeneratorTimer = ctx.spawn(
          GenericTimerActor
            .Props(renderTickGenerator, TickGenerator.Send, 10.millis)
            .behavior,
          "tickGeneratorTimer"
        )

        Behaviors.receiveMessage {
          case Start =>
            tickGeneratorTimer ! GenericTimerActor.Start
            Behaviors.same
          case Pause =>
            tickGeneratorTimer ! GenericTimerActor.Stop
            Behaviors.same
          case Stop =>
            ctx.log.info("Received stop")
            tickGeneratorTimer ! GenericTimerActor.Stop
            Behaviors.stopped

        }
      }

    val renderTickGeneratorBehavior =
      Behaviors.receiveMessage[TickGenerator.Command] {
        case Send =>
          tickEventBus ! EventBus.Publish(
            TickEvent.RenderTick,
            "tickGeneratorActor"
          )
          Behaviors.same
      }
  }
}

object TickGenerator {
  sealed trait Command
  case object Send extends Command
}
object SubscribingActor {
  def apply() =
    Behaviors.receive[PhysicsTick.type] { (ctx, msg) =>
      ctx.log.debug(s"received event $msg")
      Behaviors.same
    }
}
object Methods {

  def old() = {
    // val movementActor =
    //   ctx.spawn(
    //     MovementActor(MovementActor.Props(app, geom)),
    //     "movementActor"
    //     // DispatcherSelector.fromConfig("jme-dispatcher")
    //   )

    // val movementActorTimer = ctx.spawn(
    //   MovementActorTimer(movementActor),
    //   "movementActorTimer"
    // )
  }

  def old2() = {
    // ctx.log.info("here")

    // {
    //   implicit val s = schedulers.async
    //   Task
    //     .parZip2(
    //       loggerL.info("Test").executeOn(app.scheduler),
    //       app
    //         .enqueueL(() => loggerL.info("here 2").executeOn(app.scheduler))
    //         .flatten
    //     )
    //     .runToFuture
    // }

    // app
    //   .getRootNode()
    //   .depthFirst(s =>
    //     // s match {
    //     //   case node: Node =>
    //     //     println("node" + s.getName() + " children " + node.getChildren())
    //     //   case g: Geometry => println(s.getName())
    //     // }
    //     println(s.getName())
    //   )

    // println("----------------")

    // {
    //   app
    //     .getRootNode()
    //     .observableDepthFirst()
    //     .map(s => s.getName())
    //     // .takeWhileInclusive(_.getName() != "level")
    //     .onErrorHandle(e => e.getMessage())
    //     .foreach(println)(schedulers.async)

    // }

    // println("----------------")

    // {
    //   app
    //     .getRootNode()
    //     .observableBreadthFirst()
    //     .map(s => s.getName())
    //     // .takeWhileInclusive(_.getName() != "level")
    //     .onErrorHandle(e => e.getMessage())
    //     .foreach(println)(schedulers.async)

    // }

    // app.start()
    // Behaviors.same
  }
}

// new PlayerMovementState(
//   // movementActor,
//   // movementActorTimer,
//   imMovementActor,
//   // geom,
//   // camNode,
//   playerNode
//   // ctx.self
// )
