package ocelot.desktop.ui.widget.slot

import ocelot.desktop.color.Color
import ocelot.desktop.inventory.Items.{ArbitraryItemGroup, ExtendedTieredItemGroup, SingletonItemGroup, TieredItemGroup}
import ocelot.desktop.inventory._
import ocelot.desktop.ui.widget.contextmenu._
import totoro.ocelot.brain.util.ExtendedTier.ExtendedTier
import totoro.ocelot.brain.util.Tier.Tier

class ItemChooser[I <: Item](slot: SlotWidget[I]) extends ContextMenu {
  import ItemChooser._

  private def makeMenuEntry(factory: ItemFactory, label: String): ContextMenuEntry = {
    ContextMenuEntry(
      label,
      Some(ContextMenuIcon(factory.icon, ContextMenuIconSize.Big, Some(Color.White))),
    ) {
      slot.item = factory.build().asInstanceOf[I]
    }
  }

  private def addSubmenu[T: HasLabel](
    name: String,
    factories: Seq[(T, ItemFactory)],
    icon: Option[ContextMenuIcon] = None,
  ): Unit = {
    val tierLabel = implicitly[HasLabel[T]].label _

    val acceptedFactories = factories.iterator.filter(p => slot.isItemAccepted(p._2)).toSeq

    if (acceptedFactories.nonEmpty) {
      addEntry(
        new ContextMenuSubmenu(
          name,
          Some(
            icon.getOrElse(ContextMenuIcon(acceptedFactories.last._2.icon, ContextMenuIconSize.Big, Some(Color.White)))
          ),
        ) {
          for ((tier, factory) <- acceptedFactories) {
            addEntry(makeMenuEntry(factory, tierLabel(tier)))
          }
        }
      )
    }
  }

  for (group <- Items.groups) {
    group match {
      case SingletonItemGroup(name, factory) =>
        if (slot.isItemAccepted(factory)) {
          addEntry(makeMenuEntry(factory, name))
        }

      case TieredItemGroup(name, factories) => addSubmenu(name, factories)

      case ExtendedTieredItemGroup(name, factories) => addSubmenu(name, factories)

      case ArbitraryItemGroup(name, icon, factories) =>
        addSubmenu(name, factories, Some(ContextMenuIcon(icon, ContextMenuIconSize.Big, Some(Color.White))))
    }
  }
}

object ItemChooser {
  private trait HasLabel[A] {
    def label(value: A): String
  }

  private implicit val TierHasLabel: HasLabel[Tier] = _.label
  private implicit val ExtendedTierHasLabel: HasLabel[ExtendedTier] = _.label
  private implicit val StringHasLabel: HasLabel[String] = identity
}
