package ocelot.desktop.util

import ocelot.desktop.audio.{Audio, SoundSource}
import ocelot.desktop.color._
import ocelot.desktop.geometry.Rect2D
import ocelot.desktop.graphics.IconSource.{DiskActivityIconSource, FloppyDriveIconSource}
import ocelot.desktop.graphics.{Graphics, IconSource}
import ocelot.desktop.inventory.SyncedInventory
import ocelot.desktop.inventory.item._
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
import ocelot.desktop.ui.widget.slot._
import ocelot.desktop.ui.widget.window.Windowed
import ocelot.desktop.util.DiskDriveAware.ColorValues
import ocelot.desktop.windows.DiskDriveWindow
import totoro.ocelot.brain.entity.FloppyDiskDrive
import totoro.ocelot.brain.entity.traits.Inventory
import totoro.ocelot.brain.loot.Loot
import totoro.ocelot.brain.util.DyeColor

trait DiskDriveAware extends Logging with SyncedInventory with DefaultSlotItemsFillable with Windowed[DiskDriveWindow] {
  override type I = FloppyItem

  def floppyDiskDrive: FloppyDiskDrive

  override def brainInventory: Inventory = floppyDiskDrive.inventory.owner

  val floppySlotWidget: FloppySlotWidget = new FloppySlotWidget(Slot(0))

  def drawActivityAndFloppy(
    g: Graphics,
    bounds: Rect2D,
    iconSource: DiskActivityIconSource with FloppyDriveIconSource,
  ): Unit = {
    DrawUtils.drawFilesystemActivity(
      g,
      bounds.x,
      bounds.y,
      floppyDiskDrive,
      iconSource,
    )

    for (item <- floppySlotWidget.item) {
      g.sprite(
        iconSource.Floppy,
        bounds.x,
        bounds.y,
        bounds.w,
        bounds.h,
        IntColor(ColorValues(item.color)),
      )
    }
  }

  def isFloppyItemPresent: Boolean = floppySlotWidget.item.isDefined

  def eject(): Unit = {
    floppySlotWidget.item = None

    if (!Audio.isDisabled)
      SoundSource.MachineFloppyEject.play()
  }

  def addEjectContextMenuEntry(menu: ContextMenu): Unit = {
    menu.addEntry(ContextMenuEntry("Eject", IconSource.Icons.Eject) {
      eject()
    })
  }

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

  override def fillSlotsWithDefaultItems(): Unit = {
    floppySlotWidget.item = new FloppyItem.Factory.Loot(Loot.OpenOsFloppy).build()
  }

  // ---------------------------- WindowedNode ----------------------------

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

object DiskDriveAware {
  val ColorNames: Map[DyeColor, String] = Map(
    DyeColor.White -> "White",
    DyeColor.Orange -> "Orange",
    DyeColor.Magenta -> "Magenta",
    DyeColor.LightBlue -> "LightBlue",
    DyeColor.Yellow -> "Yellow",
    DyeColor.Lime -> "Lime",
    DyeColor.Pink -> "Pink",
    DyeColor.Gray -> "Gray",
    DyeColor.Silver -> "Silver",
    DyeColor.Cyan -> "Cyan",
    DyeColor.Purple -> "Purple",
    DyeColor.Blue -> "Blue",
    DyeColor.Brown -> "Brown",
    DyeColor.Green -> "Green",
    DyeColor.Red -> "Red",
    DyeColor.Black -> "Black",
  )

  val ColorValues: Map[DyeColor, Int] = Map(
    DyeColor.Black -> 0x444444, // 0x1E1B1B
    DyeColor.Red -> 0xb3312c,
    DyeColor.Green -> 0x339911, // 0x3B511A
    DyeColor.Brown -> 0x51301a,
    DyeColor.Blue -> 0x6666ff, // 0x253192
    DyeColor.Purple -> 0x7b2fbe,
    DyeColor.Cyan -> 0x66ffff, // 0x287697
    DyeColor.Silver -> 0xababab,
    DyeColor.Gray -> 0x666666, // 0x434343
    DyeColor.Pink -> 0xd88198,
    DyeColor.Lime -> 0x66ff66, // 0x41CD34
    DyeColor.Yellow -> 0xffff66, // 0xDECF2A
    DyeColor.LightBlue -> 0xaaaaff, // 0x6689D3
    DyeColor.Magenta -> 0xc354cd,
    DyeColor.Orange -> 0xeb8844,
    DyeColor.White -> 0xf0f0f0,
  )
}
