package ocelot.desktop.graphics

import ocelot.desktop.geometry.Size2D
import ocelot.desktop.ui.widget.modal.notification.NotificationType.NotificationType
import totoro.ocelot.brain.entity.tape.Tape.{Kind => TapeKind}
import totoro.ocelot.brain.util.DyeColor
import totoro.ocelot.brain.util.ExtendedTier.ExtendedTier
import totoro.ocelot.brain.util.Tier.Tier

case class IconSource(
  path: String,
  animation: Option[IconSource.Animation] = None,
)

object IconSource {
  val CardIcon: IconSource = IconSource("icons/Card")
  val CpuIcon: IconSource = IconSource("icons/CPU")
  val HddIcon: IconSource = IconSource("icons/HDD")
  val EepromIcon: IconSource = IconSource("icons/EEPROM")
  val FloppyIcon: IconSource = IconSource("icons/Floppy")
  val MemoryIcon: IconSource = IconSource("icons/Memory")
  val ServerIcon: IconSource = IconSource("icons/Server")
  val ComponentBusIcon: IconSource = IconSource("icons/ComponentBus")

  val TierIcon: Tier => IconSource = { tier =>
    IconSource(s"icons/Tier${tier.id}")
  }

  object Items {
    val Cpu: Tier => IconSource = { tier =>
      IconSource(s"items/CPU${tier.id}")
    }

    val Apu: Tier => IconSource = { tier =>
      IconSource(s"items/APU${tier.id}", animation = Some(Animations.Apu))
    }

    val GraphicsCard: Tier => IconSource = { tier =>
      IconSource(s"items/GraphicsCard${tier.id}")
    }

    val NetworkCard: IconSource = IconSource("items/NetworkCard")

    val WirelessNetworkCard: Tier => IconSource = { tier =>
      IconSource(s"items/WirelessNetworkCard${tier.id}")
    }

    val LinkedCard: IconSource = IconSource("items/LinkedCard", animation = Some(Animations.LinkedCard))

    val InternetCard: IconSource = IconSource("items/InternetCard", animation = Some(Animations.InternetCard))

    val RedstoneCard: Tier => IconSource = { tier =>
      IconSource(s"items/RedstoneCard${tier.id}")
    }

    val DataCard: Tier => IconSource = { tier =>
      IconSource(s"items/DataCard${tier.id}", animation = Some(Animations.DataCard))
    }

    val SoundCard: IconSource = IconSource("items/SoundCard", animation = Some(Animations.DataCard))

    val SelfDestructingCard: IconSource =
      IconSource("items/SelfDestructingCard", animation = Some(Animations.SelfDestructingCard))

    val OcelotCard: IconSource = IconSource("items/OcelotCard", animation = Some(Animations.OcelotCard))

    val HardDiskDrive: Tier => IconSource = { tier =>
      IconSource(s"items/HardDiskDrive${tier.id}")
    }

    val Eeprom: IconSource = IconSource("items/EEPROM")

    val FloppyDisk: DyeColor => IconSource = { color =>
      IconSource(s"items/FloppyDisk_${color.name}")
    }

    val Memory: ExtendedTier => IconSource = { tier =>
      IconSource(s"items/Memory${tier.id}")
    }

    val Server: Tier => IconSource = { tier =>
      IconSource(s"items/Server${tier.id}")
    }

    val ComponentBus: Tier => IconSource = { tier =>
      IconSource(s"items/ComponentBus${tier.id}")
    }

    val Tape: TapeKind => IconSource = {
      case TapeKind.Golder => Tape(TapeKind.Gold)
      case TapeKind.NetherStarrer => Tape(TapeKind.NetherStar)
      case kind => IconSource(s"items/Tape$kind")
    }

    val DiskDriveMountable: IconSource = IconSource("items/DiskDriveMountable")

    // noinspection ScalaWeakerAccess
    object Animations {
      val Apu: Animation =
        Animation((0, 3f), (1, 3f), (2, 3f), (3, 3f), (4, 3f), (5, 3f), (4, 3f), (3, 3f), (2, 3f), (1, 3f), (0, 3f))

      val LinkedCard: Animation =
        Animation((0, 3f), (1, 3f), (2, 3f), (3, 3f), (4, 3f), (5, 3f))

      val InternetCard: Animation =
        Animation((0, 2f), (1, 7f), (0, 5f), (1, 4f), (0, 7f), (1, 2f), (0, 8f), (1, 9f), (0, 6f), (1, 4f))

      val DataCard: Animation = Animation((0, 4f), (1, 4f), (2, 4f), (3, 4f), (4, 4f), (5, 4f), (6, 4f), (7, 4f))

      val SelfDestructingCard: Animation = Animation((0, 4f), (1, 4f))

      val OcelotCard: Animation =
        Animation((0, 12f), (1, 4f), (2, 4f), (3, 4f), (4, 5f), (5, 6f), (0, 9f), (6, 4f), (7, 3f))
    }
  }

  case class Animation(frames: Array[(Int, Float)], frameSize: Option[Size2D])

  object Animation {
    def apply(frames: (Int, Float)*) = new Animation(frames.toArray, None)
    def apply(size: Size2D, frames: (Int, Float)*) = new Animation(frames.toArray, Some(size))
    def apply(size: Option[Size2D] = None, frames: Array[(Int, Float)]) = new Animation(frames, size)
  }

  // ----------------------- Ocelot interface icons -----------------------

  val Notification: NotificationType => IconSource = { notificationType =>
    IconSource(s"icons/Notification$notificationType")
  }

  val Loading: IconSource = IconSource(
    "Loading",
    animation = Some(Animation(
      Size2D(48, 32),
      (0, 0.7f),
      (1, 0.7f),
      (2, 0.7f),
      (3, 0.7f),
      (4, 0.7f),
      (5, 0.7f),
      (6, 0.7f),
      (7, 0.7f),
      (8, 0.7f),
      (9, 0.7f),
      (10, 0.7f),
      (11, 0.7f),
      (12, 0.7f),
      (13, 0.7f),
    )),
  )

  val SettingsSystem: IconSource = IconSource("icons/SettingsSystem")
  val SettingsSound: IconSource = IconSource("icons/SettingsSound")
  val SettingsUI: IconSource = IconSource("icons/SettingsUI")
  val Delete: IconSource = IconSource("icons/Delete")
  val Label: IconSource = IconSource("icons/Label")
  val Copy: IconSource = IconSource("icons/Copy")
  val AspectRatio: IconSource = IconSource("icons/AspectRatio")
  val Eject: IconSource = IconSource("icons/Eject")
  val Restart: IconSource = IconSource("icons/Restart")
  val Edit: IconSource = IconSource("icons/Edit")
  val Folder: IconSource = IconSource("icons/Folder")
  val FolderSlash: IconSource = IconSource("icons/FolderSlash")
  val Code: IconSource = IconSource("icons/Code")
  val File: IconSource = IconSource("icons/File")
  val Link: IconSource = IconSource("icons/Link")
  val LinkSlash: IconSource = IconSource("icons/LinkSlash")
  val Power: IconSource = IconSource("icons/Power")
  val Save: IconSource = IconSource("icons/Save")
  val SaveAs: IconSource = IconSource("icons/SaveAs")
  val Plus: IconSource = IconSource("icons/Plus")
  val Cross: IconSource = IconSource("icons/Cross")
  val Microchip: IconSource = IconSource("icons/Microchip")
  val Antenna: IconSource = IconSource("icons/Antenna")
  val Window: IconSource = IconSource("icons/Window")
  val Tiers: IconSource = IconSource("icons/Tiers")
  val LinesHorizontal: IconSource = IconSource("icons/LinesHorizontal")
  val ArrowRight: IconSource = IconSource("icons/ArrowRight")
  val Book: IconSource = IconSource("icons/Book")
  val Help: IconSource = IconSource("icons/Help")
  val Ocelot: IconSource = IconSource("icons/Ocelot")
  val Guitar: IconSource = IconSource("icons/Guitar")
  val Keyboard: IconSource = IconSource("icons/Keyboard")
  val KeyboardOff: IconSource = IconSource("icons/KeyboardOff")

  // ----------------------- Node icons -----------------------

  val NA: IconSource = IconSource("icons/NA")

  object Nodes {
    val NewNode: IconSource = IconSource("nodes/NewNode")

    val Cable: IconSource = IconSource("nodes/Cable")
    val Camera: IconSource = IconSource("nodes/Camera")
    val Chest: IconSource = IconSource("nodes/Chest")

    val HologramProjector: Tier => IconSource = { tier =>
      IconSource(s"nodes/HologramProjector${tier.id}")
    }

    val IronNoteBlock: IconSource = IconSource("nodes/IronNoteBlock")
    val NoteBlock: IconSource = IconSource("nodes/NoteBlock")
    val OpenFMRadio: IconSource = IconSource("nodes/OpenFMRadio")
    val Relay: IconSource = IconSource("nodes/Relay")
    val TapeDrive: IconSource = IconSource("nodes/TapeDrive")

    object Computer extends PowerIconSource with DiskActivityIconSource {
      override protected def prefix: String = "nodes/computer"

      val Default: IconSource = IconSource(s"$prefix/Default")
    }

    object DiskDrive extends DiskActivityIconSource with FloppyDriveIconSource {
      override protected def prefix: String = "nodes/disk-drive"

      val Default: IconSource = IconSource(s"$prefix/Default")
    }

    object Lamp extends IconSource("nodes/Lamp") {
      val Frame: IconSource = IconSource("nodes/LampFrame")
      val Glow: IconSource = IconSource("nodes/LampGlow")
    }

    object Microcontroller extends PowerIconSource {
      override protected def prefix: String = "nodes/microcontroller"

      val Default: IconSource = IconSource(s"$prefix/Default")
    }

    object OcelotBlock {
      val Default: IconSource = IconSource(
        "nodes/ocelot-block/Default",
        animation = Some(Animation(Size2D(16, 16), (0, 30f), (1, 5f), (2, 2f), (0, 20f), (3, 3f), (4, 2f))),
      )

      val Rx: IconSource = IconSource("nodes/ocelot-block/Rx")
      val Tx: IconSource = IconSource("nodes/ocelot-block/Tx")
    }

    object Rack {
      protected val prefix: String = "nodes/rack"

      val Empty: IconSource = IconSource(s"$prefix/Empty")
      val Default: IconSource = IconSource(s"$prefix/Default")

      val Server: Array[Server] = Array.tabulate(4)(new Server(_))
      val Drive: Array[Drive] = Array.tabulate(4)(new Drive(_))

      class Server(val slot: Int) extends PowerIconSource with DiskActivityIconSource with NetworkActivityIconSource {
        override protected def prefix: String = s"${Rack.prefix}/server/$slot"

        val Default: IconSource = IconSource(s"$prefix/Default")
      }

      class Drive(val slot: Int) extends DiskActivityIconSource with FloppyDriveIconSource {
        override protected def prefix: String = s"${Rack.prefix}/drive/$slot"

        val Default: IconSource = IconSource(s"$prefix/Default")
      }
    }

    object Raid {
      protected val prefix: String = "nodes/raid"

      val Default: IconSource = IconSource(s"$prefix/Default")

      val Drive: Array[Drive] = Array.tabulate(3)(new Drive(_))

      class Drive(val slot: Int) extends DiskActivityIconSource {
        override protected def prefix: String = s"${Raid.prefix}/$slot"

        val Error: IconSource = IconSource(s"$prefix/Error")
      }
    }

    object Screen {
      protected val prefix: String = "nodes/screen"

      val Standalone: IconSource = IconSource(s"$prefix/Standalone")
      val PowerOnOverlay: IconSource = IconSource(s"$prefix/PowerOnOverlay")

      val ColumnTop: IconSource = IconSource(s"$prefix/ColumnTop")
      val ColumnMiddle: IconSource = IconSource(s"$prefix/ColumnMiddle")
      val ColumnBottom: IconSource = IconSource(s"$prefix/ColumnBottom")

      val RowLeft: IconSource = IconSource(s"$prefix/RowLeft")
      val RowMiddle: IconSource = IconSource(s"$prefix/RowMiddle")
      val RowRight: IconSource = IconSource(s"$prefix/RowRight")

      val TopLeft: IconSource = IconSource(s"$prefix/TopLeft")
      val TopMiddle: IconSource = IconSource(s"$prefix/TopMiddle")
      val TopRight: IconSource = IconSource(s"$prefix/TopRight")

      val MiddleLeft: IconSource = IconSource(s"$prefix/MiddleLeft")
      val Middle: IconSource = IconSource(s"$prefix/Middle")
      val MiddleRight: IconSource = IconSource(s"$prefix/MiddleRight")

      val BottomLeft: IconSource = IconSource(s"$prefix/BottomLeft")
      val BottomMiddle: IconSource = IconSource(s"$prefix/BottomMiddle")
      val BottomRight: IconSource = IconSource(s"$prefix/BottomRight")
    }

    object Holidays {
      protected val prefix: String = "nodes/holidays"

      val Christmas: IconSource = IconSource(s"$prefix/Christmas")
      val Valentines: IconSource = IconSource(s"$prefix/Valentines")
      val Halloween: IconSource = IconSource(s"$prefix/Halloween")
    }
  }

  trait PowerIconSource {
    protected def prefix: String

    val On: IconSource = IconSource(s"$prefix/On")
    val Error: IconSource = IconSource(s"$prefix/Error")
  }

  trait DiskActivityIconSource {
    protected def prefix: String

    val DiskActivity: IconSource = IconSource(s"$prefix/DiskActivity")
  }

  trait NetworkActivityIconSource {
    protected def prefix: String

    val NetworkActivity: IconSource = IconSource(s"$prefix/NetworkActivity")
  }

  trait FloppyDriveIconSource {
    protected def prefix: String

    val Floppy: IconSource = IconSource(s"$prefix/Floppy")
  }
}
