package wow.doge.mygame.utils

import scala.concurrent.duration.FiniteDuration
import scala.util.Random

import akka.actor.typed.ActorRef
import akka.actor.typed.Behavior
import akka.actor.typed.scaladsl.ActorContext
import akka.actor.typed.scaladsl.Behaviors
import akka.actor.typed.scaladsl.TimerScheduler
import wow.doge.mygame.implicits._

object GenericTimerActor {
  sealed trait Command
  case object Start extends Command
  case object Stop extends Command
  private case object Tick extends Command
  case class TimerKey(seed: Long)

  case class Props[T](
      target: ActorRef[T],
      messageToSend: T,
      timeInterval: FiniteDuration
  ) {
    def behavior =
      Behaviors.withTimers[Command] { timers =>
        Behaviors.setup { ctx =>
          new GenericTimerActor(
            ctx,
            timers,
            TimerKey(Random.nextLong()),
            this
          ).idle
        }
      }
  }
}
class GenericTimerActor[T](
    ctx: ActorContext[GenericTimerActor.Command],
    timers: TimerScheduler[GenericTimerActor.Command],
    timerKey: GenericTimerActor.TimerKey,
    props: GenericTimerActor.Props[T]
) {
  import GenericTimerActor._

  val idle: Behavior[Command] =
    Behaviors.receiveMessage {
      case Start =>
        timers.startTimerWithFixedDelay(timerKey, Tick, props.timeInterval)
        active
      case _ => Behaviors.unhandled

    }

  val active: Behavior[Command] =
    Behaviors.receiveMessage {
      case Start =>
        ctx.log.warnP(s"Timer-${timerKey.seed}: Timer already started")
        Behaviors.same
      case Tick =>
        props.target ! props.messageToSend
        Behaviors.same
      case Stop =>
        timers.cancel(timerKey)
        idle
    }
}
