package ocelot.desktop.windows

import ocelot.desktop.ColorScheme
import ocelot.desktop.color.Color
import ocelot.desktop.geometry.Size2D
import ocelot.desktop.inventory.ItemFactory
import ocelot.desktop.inventory.item.{LinkedCardItem, WirelessNetworkCardItem}
import ocelot.desktop.node.nodes.RelayNode
import ocelot.desktop.ui.layout.{AlignItems, JustifyContent, Layout, LinearLayout}
import ocelot.desktop.ui.widget.slot.{CardSlotWidget, CpuSlotWidget, HddSlotWidget, MemorySlotWidget}
import ocelot.desktop.ui.widget.window.PanelWindow
import ocelot.desktop.ui.widget.{Label, Widget}
import ocelot.desktop.util.Orientation
import ocelot.desktop.windows.RelayWindow.{LabelWidth, TransferRateFormat}
import totoro.ocelot.brain.util.Tier
import totoro.ocelot.brain.util.Tier.Tier

import java.text.DecimalFormat

class RelayWindow(val node: RelayNode) extends PanelWindow {
  override protected def title: String = "Relay"

  private def makeLabel(_text: => String): Label = new Label {
    override def text: String = _text

    override def minimumSize: Size2D = super.minimumSize.copy(width = LabelWidth)

    override def maximumSize: Size2D = minimumSize
  }

  setInner(new Widget {
    override protected val layout: Layout = new LinearLayout(this, orientation = Orientation.Vertical, gap = 4f)

    // CPU
    children :+= new Widget {
      override protected val layout: Layout = new LinearLayout(
        this,
        orientation = Orientation.Horizontal,
        alignItems = AlignItems.Center,
        gap = 8f,
      )

      children :+= makeLabel("Cycle rate")

      children :+= new Label {
        override def text: String = s"${TransferRateFormat.format(20f / node.relay.relayDelay)}"
      }

      children :+= new CpuSlotWidget(node.Slot(node.relay.cpuSlot.index), Tier.Three) {
        override def slotTier: Option[Tier] = None
      }
    }

    // Memory
    children :+= new Widget {
      override protected val layout: Layout = new LinearLayout(
        this,
        orientation = Orientation.Horizontal,
        alignItems = AlignItems.Center,
        gap = 8f,
      )

      children :+= makeLabel("Packets / cycle")

      children :+= new Label {
        override def text: String = s"${node.relay.packetsPerCycleAvg()} / ${node.relay.relayAmount}"

        override def color: Color = thresholdBasedColor(
          node.relay.packetsPerCycleAvg(),
          (node.relay.relayAmount / 2f).ceil.toInt,
          node.relay.relayAmount,
        )
      }

      children :+= new MemorySlotWidget(node.Slot(node.relay.memorySlot.index), Tier.Three) {
        override def slotTier: Option[Tier] = None
      }
    }

    // HDD
    children :+= new Widget {
      override protected val layout: Layout = new LinearLayout(
        this,
        orientation = Orientation.Horizontal,
        alignItems = AlignItems.Center,
        gap = 8f,
      )

      children :+= makeLabel("Queue size")

      children :+= new Label {
        override def text: String = s"${node.relay.queue.size} / ${node.relay.maxQueueSize}"

        override def color: Color = thresholdBasedColor(
          node.relay.queue.size,
          node.relay.maxQueueSize / 2,
          node.relay.maxQueueSize,
        )
      }

      children :+= new HddSlotWidget(node.Slot(node.relay.hddSlot.index), Tier.Three) {
        override def slotTier: Option[Tier] = None
      }
    }

    // Network card
    children :+= new Widget {
      override protected val layout: Layout = new LinearLayout(
        this,
        orientation = Orientation.Horizontal,
        justifyContent = JustifyContent.End,
        gap = 8f,
      )

      override def maximumSize: Size2D = super.maximumSize.copy(width = Float.PositiveInfinity)

      children :+= new CardSlotWidget(node.Slot(node.relay.networkCardSlot.index), Tier.Three) {
        override def slotTier: Option[Tier] = None

        override def isItemAccepted(factory: ItemFactory): Boolean = {
          super.isItemAccepted(factory) &&
          Array(classOf[WirelessNetworkCardItem], classOf[LinkedCardItem])
            .exists(_.isAssignableFrom(factory.itemClass))
        }
      }
    }
  })

  private def thresholdBasedColor(value: Int, mid: Int, high: Int): Color = {
    if (value < mid) {
      ColorScheme("RelayTextLow")
    } else if (value < high) {
      ColorScheme("RelayTextMid")
    } else {
      ColorScheme("RelayTextHigh")
    }
  }
}

object RelayWindow {
  private val TransferRateFormat = new DecimalFormat("#.##hz")
  private val LabelWidth = 130
}
