package ocelot.desktop.node.nodes

import ocelot.desktop.color.RGBAColorNorm
import ocelot.desktop.entity.OcelotBlock
import ocelot.desktop.entity.traits.OcelotInterface
import ocelot.desktop.util.NumberUtils.ExtendedFloat
import ocelot.desktop.graphics.{Graphics, IconSource}
import ocelot.desktop.node.Node.HighlightThickness
import ocelot.desktop.node.nodes.OcelotBlockNode.ActivityFadeOutMs
import ocelot.desktop.node.{EntityNode, LabeledEntityNode, OcelotLogParticleNode, WindowedNode}
import ocelot.desktop.ui.widget.LogWidget
import ocelot.desktop.ui.widget.LogWidget.LogEntry
import ocelot.desktop.util.OcelotInterfaceLogStorage
import ocelot.desktop.windows.OcelotInterfaceWindow

class OcelotBlockNode(val ocelot: OcelotBlock)
    extends EntityNode(ocelot)
    with LabeledEntityNode
    with OcelotLogParticleNode
    with OcelotInterfaceLogStorage
    with WindowedNode[OcelotInterfaceWindow] {

  override def name: String = "Ocelot Block"

  override def icon: IconSource = IconSource.Nodes.OcelotBlock.Default

  override def rotatable: Boolean = false

  override def ocelotInterface: OcelotInterface = ocelot

  private var lastRx: Long = -1L
  private var lastTx: Long = -1L

  override protected def onMessagesAdded(entries: => Iterable[LogWidget.LogEntry]): Unit = {
    super.onMessagesAdded(entries)

    var hasRx = false
    var hasTx = false

    for (entry <- entries.iterator.takeWhile(_ => !hasRx || !hasTx)) {
      entry match {
        case _: LogEntry.Rx => hasRx = true
        case _: LogEntry.Tx => hasTx = true
      }
    }

    val t = System.currentTimeMillis()

    if (hasRx) {
      lastRx = t
    }

    if (hasTx) {
      lastTx = t
    }
  }

  override def draw(g: Graphics): Unit = {
    super.draw(g)

    val t = System.currentTimeMillis()
    drawActivity(g, IconSource.Nodes.OcelotBlock.Rx, lastRx, t)
    drawActivity(g, IconSource.Nodes.OcelotBlock.Tx, lastTx, t)
  }

  private def drawActivity(g: Graphics, icon: IconSource, lastActivity: Long, currentTime: Long): Unit = {
    val alpha = (1 - (currentTime - lastActivity) / ActivityFadeOutMs).clamped()

    if (alpha > 0) {
      g.sprite(
        icon,
        position.x + HighlightThickness,
        position.y + HighlightThickness,
        size.width - HighlightThickness * 2,
        size.height - HighlightThickness * 2,
        RGBAColorNorm(1f, 1f, 1f, alpha),
      )
    }
  }
}

object OcelotBlockNode {
  private val ActivityFadeOutMs: Float = 300f
}
