package ocelot.desktop.node.nodes

import ocelot.desktop.graphics.Graphics
import ocelot.desktop.inventory.item.HddItem
import ocelot.desktop.inventory.traits.DiskItem
import ocelot.desktop.inventory.{Item, SyncedInventory}
import ocelot.desktop.node.Node.{HighlightThickness, NoHighlightSize}
import ocelot.desktop.node.{EntityNode, LabeledEntityNode, WindowedNode}
import ocelot.desktop.ui.event.ClickEvent
import ocelot.desktop.ui.event.handlers.DiskActivityHandler
import ocelot.desktop.ui.widget.contextmenu.ContextMenu
import ocelot.desktop.ui.widget.slot.HddSlotWidget
import ocelot.desktop.util.{DefaultSlotItemsFillable, DrawUtils}
import ocelot.desktop.windows.RaidWindow
import totoro.ocelot.brain.entity.Raid
import totoro.ocelot.brain.entity.traits.Inventory
import totoro.ocelot.brain.util.Tier

import scala.util.Random

class RaidNode(val raid: Raid) extends
  EntityNode(raid)
  with SyncedInventory
  with LabeledEntityNode
  with DiskActivityHandler
  with DefaultSlotItemsFillable
  with WindowedNode[RaidWindow]
{
  var diskSlots: Array[HddSlotWidget] = Array.tabulate(3)(index => new HddSlotWidget(Slot(index), Tier.Three))

  override val icon: String = "nodes/raid/Default"

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

    val x = position.x + HighlightThickness
    val y = position.y + HighlightThickness
    var prefix: String = null

    for (i <- 0 until raid.getSizeInventory) {
      prefix = s"nodes/raid/$i/"

      // Missing disks overlay
      if (Slot(i).isEmpty)
        g.sprite(s"${prefix}Error", x, y, NoHighlightSize, NoHighlightSize)

      // Disk activity overlay
      if (raid.shouldVisualizeDiskActivity && Random.nextDouble() > 0.1 && i == raid.lastDiskAccess % raid.getSizeInventory) {
        DrawUtils.drawFilesystemActivity(
          g,
          x,
          y,
          prefix
        )
      }
    }
  }

  // Required for disk activity events processing
  override def shouldReceiveEventsFor(address: String): Boolean =
    super.shouldReceiveEventsFor(address) || raid.filesystem.exists(_.node.address == address)

  override def setupContextMenu(menu: ContextMenu, event: ClickEvent): Unit = {
    DiskItem.addRealPathContextMenuEntries(menu, raid, realPathSetter => {
      realPathSetter()
    })

    // TODO: Implement DiskDriveWindow later, because at this moment every
    // TODO: instance of 'Windowed' trait can have only 1 persistable window

    // TODO: Perhaps we should rework this system with List[Window] and
    // TODO: registerWindow(...) or something similar

//    menu.addEntry(ContextMenuEntry("Edit disk", IconSource.Edit) {
//      window.open()
//    })

    menu.addSeparator()

    super.setupContextMenu(menu, event)
  }

  // -------------------------------- LabeledEntityNode --------------------------------

  override def fallbackLabelAddress: Option[String] = raid.filesystem.map(_.node.address)

  // -------------------------------- Inventory --------------------------------

  override type I = Item with HddItem

  override def brainInventory: Inventory = raid.inventory.owner

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

  override def fillSlotsWithDefaultItems(): Unit = {
    for (i <- diskSlots.indices)
      diskSlots(i).setItem(new HddItem.Factory(true, Tier.Three).build())
  }

  // -------------------------------- Window --------------------------------

  override def createWindow(): RaidWindow = new RaidWindow(this)
}
