package devbox.logger

import java.time.Duration

object StatusActor{
  sealed trait Msg
  case class SetIcon(iconName: String, msg: Seq[String]) extends Msg
  case class Debounce() extends Msg
}

class StatusActor(setImage: String => Unit,
                  setTooltip: String => Unit)
                 (implicit ac: castor.Context)
extends castor.StateMachineActor[StatusActor.Msg]{

  def initialState = StatusState(
    StatusActor.SetIcon("blue-tick", Seq("Devbox initializing")),
    DebounceIdle(),
  )

  sealed trait DebounceState
  case class DebounceIdle() extends DebounceState
  case class DebounceCooldown() extends DebounceState
  case class DebounceFull(value: StatusActor.SetIcon) extends DebounceState

  case class StatusState(icon: StatusActor.SetIcon,
                         debounced: DebounceState) extends State{
    override def run = {
      case msg: StatusActor.SetIcon => debounceReceive(msg)
      case StatusActor.Debounce() =>
        debounced match{
          case DebounceFull(n) => statusMsgToState(DebounceIdle(), n)
          case ds => this.copy(debounced = DebounceIdle())
        }
    }

    def debounceReceive(statusMsg: StatusActor.SetIcon): State = {
      if (debounced == DebounceIdle()) {
        ac.scheduleMsg(StatusActor.this, StatusActor.Debounce(), Duration.ofMillis(100))
        statusMsgToState(DebounceCooldown(), statusMsg)
      } else {
        StatusState(icon, DebounceFull(statusMsg))
      }
    }

    def statusMsgToState(newDebounced: DebounceState,
                         statusMsg: StatusActor.SetIcon): StatusState = {
      setIcon(icon, statusMsg)

      this.copy(debounced = newDebounced, icon = statusMsg)
    }
  }

  def setIcon(icon: StatusActor.SetIcon, nextIcon: StatusActor.SetIcon) = {
    if (icon.iconName != nextIcon.iconName) setImage(nextIcon.iconName)
    if (icon.msg != nextIcon.msg) setTooltip(nextIcon.msg.mkString("\n"))
  }
}