package ocelot.desktop.inventory.item

import ocelot.desktop.graphics.IconSource
import ocelot.desktop.inventory.traits.{ComponentItem, DiskItem, PersistableItem}
import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer}
import ocelot.desktop.ui.widget.DiskEditWindow
import ocelot.desktop.ui.widget.tooltip.ItemTooltip
import totoro.ocelot.brain.entity.fs.ReadWriteLabel
import totoro.ocelot.brain.entity.traits.{Disk, Entity, Floppy}
import totoro.ocelot.brain.entity.{FloppyManaged, FloppyUnmanaged}
import totoro.ocelot.brain.loot.Loot.{LootFloppy, FloppyFactory => LootFloppyFactory}
import totoro.ocelot.brain.util.DyeColor
import totoro.ocelot.brain.util.Tier.Tier

class FloppyItem(var floppy: Floppy)
  extends Item
    with ComponentItem
    with PersistableItem
    with DiskItem
    with DiskEditWindow.HasColor {

  override def entity: Entity with Disk = floppy

  override def diskKind: String = "Floppy"

  override def name: String = floppy.name.getOrElse(super.name)

  override def diskLabel: Option[String] = floppy.label.labelOption

  override def diskLabel_=(label: Option[String]): Unit = {
    floppy.label.setLabel(label.orNull)
  }

  override def isLabelWriteable: Boolean = floppy.label.isInstanceOf[ReadWriteLabel]

  override def color: DyeColor = floppy.color

  override def color_=(color: DyeColor): Unit = {
    floppy.color = color
  }

  override def setManaged(managed: Boolean): Unit = {
    val label = this.diskLabel

    reinserting {
      floppy =
        if (managed) new FloppyManaged(floppy.name, floppy.color)
        else new FloppyUnmanaged(floppy.name, floppy.color)
    }

    diskLabel = label
  }

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

    for (label <- diskLabel) {
      if (label != name) {
        // this is true for loot floppies
        addDiskLabelTooltip(tooltip, label)
      }
    }

    floppy match {
      case floppy: FloppyManaged => addSourcePathTooltip(tooltip, floppy)
      case _ => // unmanaged floppies don't need any special entries
    }

    addManagedTooltip(tooltip, floppy)
  }

  override def factory: FloppyItem.Factory = floppy match {
    case floppy: LootFloppy =>
      new FloppyItem.Factory.Loot(new LootFloppyFactory(floppy.name.get, floppy.color, floppy.path))

    case floppy: FloppyManaged =>
      new FloppyItem.Factory.Managed(floppy.label.labelOption, floppy.color)

    case floppy: FloppyUnmanaged =>
      new FloppyItem.Factory.Unmanaged(floppy.label.labelOption, floppy.color)
  }
}

object FloppyItem {
  abstract class Factory(val label: Option[String], val color: DyeColor, managed: Boolean) extends ItemFactory {
    override type I = FloppyItem

    override def itemClass: Class[I] = classOf

    override def name: String = label.getOrElse("Floppy Disk")

    override def tier: Option[Tier] = None

    override def icon: IconSource = IconSource.Items.FloppyDisk(color)

    override def recoverers: Iterable[ItemRecoverer[_, _]] = Some(ItemRecoverer(new FloppyItem(_)))
  }

  object Factory {
    class Loot(factory: LootFloppyFactory) extends Factory(Some(factory.name), factory.color, managed = true) {
      override def name: String = factory.name

      override def build(): FloppyItem = new FloppyItem(factory.create())
    }

    object Empty extends Factory(None, DyeColor.Gray, managed = true) {
      override def build(): FloppyItem = new FloppyItem(new FloppyManaged)
    }

    class Managed(label: Option[String], color: DyeColor) extends Factory(label, color, managed = true) {
      override def build(): FloppyItem = new FloppyItem(new FloppyManaged(label, color))
    }

    class Unmanaged(label: Option[String], color: DyeColor) extends Factory(label, color, managed = false) {
      override def build(): FloppyItem = new FloppyItem(new FloppyUnmanaged(label, color))
    }
  }
}
