package ocelot.desktop.node.nodes

import ocelot.desktop.graphics.{Graphics, IconSource}
import ocelot.desktop.inventory.item._
import ocelot.desktop.node.Node.HighlightThickness
import ocelot.desktop.node.{ComputerAwareNode, NodePort, WindowedNode}
import ocelot.desktop.ui.event.ClickEvent
import ocelot.desktop.ui.widget.contextmenu.ContextMenu
import ocelot.desktop.ui.widget.slot._
import ocelot.desktop.util.ComputerType.ComputerType
import ocelot.desktop.util.{ComputerAware, ComputerType, DefaultSlotItemsFillable, DrawUtils}
import ocelot.desktop.windows.ComputerWindow
import totoro.ocelot.brain.entity.Microcontroller
import totoro.ocelot.brain.entity.traits.Inventory
import totoro.ocelot.brain.network
import totoro.ocelot.brain.util.{Direction, Tier}

class MicrocontrollerNode(val microcontroller: Microcontroller)
    extends ComputerAwareNode(microcontroller)
    with ComputerAware
    with DefaultSlotItemsFillable
    with WindowedNode[ComputerWindow] {

  override val icon: IconSource = IconSource.Nodes.Microcontroller.Default

  override def setupContextMenu(menu: ContextMenu, event: ClickEvent): Unit = {
    addPowerContextMenuEntries(menu)
    addTierContextMenuEntries(menu, Tier.Two)

    menu.addSeparator()

    super.setupContextMenu(menu, event)
  }

  override def drawOverlay(g: Graphics): Unit = {
    DrawUtils.drawPowerOrError(
      g,
      position.x + HighlightThickness,
      position.y + HighlightThickness,
      microcontroller.machine,
      IconSource.Nodes.Microcontroller,
    )

    super.drawOverlay(g)
  }

  override def ports: Array[NodePort] = Array(
    NodePort(Some(Direction.Bottom)),
    NodePort(Some(Direction.Top)),
    NodePort(Some(Direction.Back)),
    NodePort(Some(Direction.Right)),
    NodePort(Some(Direction.Left)),
  )

  override def getNodeByPort(port: NodePort): network.Node =
    microcontroller.sidedNode(port.direction.get)

  override def rotatable: Boolean = true

  override def shouldReceiveEventsFor(address: String): Boolean = {
    address == microcontroller.machine.node.address ||
    super.shouldReceiveEventsFor(address)
  }

  // ---------------------------- ComputerAware ----------------------------

  override def computer: Microcontroller = microcontroller
  override def computerType: ComputerType = ComputerType.Microcontroller
  override def brainInventory: Inventory = microcontroller.inventory.owner

  override protected def selfDestructingCards: IterableOnce[SelfDestructingCardItem] = {
    inventoryIterator.flatMap(_.get).collect {
      case item: SelfDestructingCardItem => item
    }
  }

  override def addSlotsBasedOnTier(): Unit = {
    microcontroller.tier match {
      case Tier.One =>
        cardSlots = addSlotWidgets(
          new CardSlotWidget(_, Tier.One),
          new CardSlotWidget(_, Tier.One),
        )

        cpuSlot = addSlotWidget(new ComputerCpuSlotWidget(_, this, Tier.One))

        memorySlots = addSlotWidgets(
          new MemorySlotWidget(_, Tier.One),
          new MemorySlotWidget(_, Tier.One),
        )

        eepromSlot = addSlotWidget(new EepromSlotWidget(_))

      case Tier.Two =>
        cardSlots = addSlotWidgets(
          new CardSlotWidget(_, Tier.Two),
          new CardSlotWidget(_, Tier.One),
        )

        cpuSlot = addSlotWidget(new ComputerCpuSlotWidget(_, this, Tier.One))

        memorySlots = addSlotWidgets(
          new MemorySlotWidget(_, Tier.One),
          new MemorySlotWidget(_, Tier.One),
        )

        eepromSlot = addSlotWidget(new EepromSlotWidget(_))

      // Creative
      case _ =>
        cardSlots = addSlotWidgets(
          new CardSlotWidget(_, Tier.Three),
          new CardSlotWidget(_, Tier.Three),
        )

        cpuSlot = addSlotWidget(new ComputerCpuSlotWidget(_, this, Tier.Three))

        memorySlots = addSlotWidgets(
          new MemorySlotWidget(_, Tier.Three),
          new MemorySlotWidget(_, Tier.Three),
        )

        eepromSlot = addSlotWidget(new EepromSlotWidget(_))

    }
  }

  // ---------------------------- DefaultSlotItemsFillable ----------------------------

  override def fillSlotsWithDefaultItems(): Unit = {
    cardSlots(0).item = {
      if (microcontroller.tier >= Tier.Two) {
        WirelessNetworkCardItem.Tier2.Factory.build()
      } else {
        WirelessNetworkCardItem.Tier1.Factory.build()
      }
    }

    cardSlots(1).item = {
      if (microcontroller.tier == Tier.Creative) {
        RedstoneCardItem.Tier2.Factory.build()
      } else {
        RedstoneCardItem.Tier1.Factory.build()
      }
    }

    cpuSlot.item = new CpuItem.Factory(Tier.One).build()

    for (memorySlot <- memorySlots) {
      memorySlot.item = new MemoryItem.Factory(Tier.One.toExtended(false)).build()
    }

    eepromSlot.item = EepromItem.Factory.Empty.build()
  }

  // ---------------------------- ShiftClickNode ----------------------------

  override protected def onShiftClick(event: ClickEvent): Unit = toggleIsTurnedOn()

  override protected def hoveredShiftStatusBarText: String = if (computer.machine.isRunning) "Turn off" else "Turn on"
}
