package ocelot.desktop.inventory

import ocelot.desktop.ColorScheme
import ocelot.desktop.color.Color
import ocelot.desktop.graphics.IconSource
import ocelot.desktop.ui.event.EventAware
import ocelot.desktop.ui.widget.Updatable
import ocelot.desktop.ui.widget.contextmenu.ContextMenu
import ocelot.desktop.ui.widget.tooltip.ItemTooltip
import ocelot.desktop.util.Disposable
import totoro.ocelot.brain.util.Tier
import totoro.ocelot.brain.util.Tier.Tier

/** Something that can be stored in an [[Inventory]]. */
trait Item extends EventAware with Updatable with Disposable {
  private var _slot: Option[Inventory#Slot] = None

  /** The slot this item is stored in. */
  def slot: Option[Inventory#Slot] = _slot

  private[inventory] def slot_=(slot: Option[Inventory#Slot]): Unit = {
    _slot = slot

    if (slot.nonEmpty) {
      onInserted()
    } else {
      onRemoved()
    }
  }

  /** Remove the item from its slot, apply `f`, and put it back into the slot. */
  def reinserting(f: => Unit): Unit = {
    val prevSlot = slot
    slot.foreach(_.remove())
    f
    prevSlot.foreach(slot => slot.put(this.asInstanceOf[slot.inventory.I]))
  }

  /** Sends a `notification` to observers of the `slot`.
    *
    * (Which means, if the item is not put into any slot, nobody will receive the message.)
    */
  final def notifySlot(notification: Item.Notification): Unit = {
    slot.foreach(_.notifySlot(notification))
  }

  protected def onInserted(): Unit = {}

  protected def onRemoved(): Unit = {}

  /** The name of the item (as shown in the tooltip). */
  def name: String = factory.name

  /** The icon used to draw the item in a slot. */
  def icon: IconSource = factory.icon

  /** The tier of the item (if it has one).
    *
    * This affects the color of the item name in the tooltip.
    */
  def tier: Option[Tier] = factory.tier

  protected def tooltipNameColor: Color = ColorScheme(s"Tier${tier.getOrElse(Tier.One).id}")

  /** Override this in subclasses to customize the contents of the tooltip.
    *
    * @example {{{
    *            override protected def fillTooltipBody(body: Widget): Unit = {
    *              super.fillTooltipBody(body)
    *              body.children :+= new Label {
    *                override def text: String = "Hello world"
    *                override def color: Color = Color.Grey
    *              }
    *            }
    *          }}}
    */
  def fillTooltip(tooltip: ItemTooltip): Unit = {
    tooltip.addLine(name, tooltipNameColor)
  }

  /** Override this in subclasses to add new entries to the context menu.
    *
    * It usually makes sense to call `super.fillRmbMenu` ''after'' you've added your own entries.
    */
  def fillRmbMenu(menu: ContextMenu): Unit = {}

  /** The factory that can be used to build an independent instance of this [[Item]]
    * in a way equivalent to this one (e.g. the same tier, label, EEPROM code).
    *
    * Keep this rather cheap.
    */
  def factory: ItemFactory

  /** Override this in subclasses to implement some specific item behavior
    * during UI update
    */
  override def update(): Unit = {}
}

object Item {

  /** A notification that can be sent with [[Item.notifySlot]]. */
  trait Notification
}
