package ocelot.desktop.inventory.traits

import ocelot.desktop.OcelotDesktop
import ocelot.desktop.graphics.IconSource
import ocelot.desktop.inventory.Item
import ocelot.desktop.ui.UiHandler
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
import ocelot.desktop.ui.widget.tooltip.ItemTooltip
import totoro.ocelot.brain.entity.traits.{Entity, Environment, WorkspaceAware}

/**
  * Implemented by [[Item]]s that wrap a component.
  *
  * @note Subclasses must provide a unary constructor that accepts the [[component]].
  */
trait ComponentItem extends Item with PersistableItem {
  /**
    * The component wrapped by this item.
    *
    * @note The value must already be available during the initialization.
    */
  def component: Entity with Environment

  private def setWorkspace(): Unit = component match {
    case component: WorkspaceAware => component.workspace = OcelotDesktop.workspace
    case _ =>
  }

  override def reinserting(f: => Unit): Unit = super.reinserting {
    // removal may have set the workspace to null
    setWorkspace()

    f

    // since we have absolutely no idea what f does, workspace could've been set to null again
    setWorkspace()
  }

  setWorkspace()

  override def onInserted(): Unit = {
    super.onInserted()

    // this one isn't strictly necessary, I believe, but I'll keep this for the sake of symmetry and safety
    setWorkspace()
  }

  override def onRemoved(): Unit = {
    super.onRemoved()

    // fix up ComponentInventory's zeroing out the workspace
    setWorkspace()
  }

  override def shouldReceiveEventsFor(address: String): Boolean =
    super.shouldReceiveEventsFor(address) || Option(component.node).exists(_.address == address)

  override def fillTooltip(tooltip: ItemTooltip): Unit = {
    super.fillTooltip(tooltip)

    if (showAddress) {
      tooltip.addLine(s"Address: ${component.node.address}")
    }
  }

  override def fillRmbMenu(menu: ContextMenu): Unit = {
    menu.addEntry(ContextMenuEntry("Copy address", IconSource.Copy) {
      UiHandler.clipboard = component.node.address
    })

    super.fillRmbMenu(menu)
  }

  def showAddress: Boolean = true
}
