package ocelot.desktop.inventory.item

import ocelot.desktop.audio.{Audio, SoundCategory, SoundSamples, SoundSource, SoundStream}
import ocelot.desktop.graphics.IconSource
import ocelot.desktop.inventory.traits.{CardItem, ComponentItem, PersistableItem}
import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer}
import ocelot.desktop.ui.event.BrainEvent
import ocelot.desktop.ui.widget.card.SoundCardWindow
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
import ocelot.desktop.ui.widget.window.Windowed
import ocelot.desktop.util.Lazy
import totoro.ocelot.brain.Settings
import totoro.ocelot.brain.entity.sound_card.SoundCard
import totoro.ocelot.brain.event.SoundCardAudioEvent
import totoro.ocelot.brain.util.Tier
import totoro.ocelot.brain.util.Tier.Tier

class SoundCardItem(val soundCard: SoundCard)
  extends Item
    with ComponentItem
    with PersistableItem
    with CardItem
    with Windowed[SoundCardWindow] {

  override def createWindow(): SoundCardWindow = new SoundCardWindow(soundCard)

  override def entity: SoundCard = soundCard

  private val streamPair = Lazy(Audio.newStream(SoundCategory.Records))
  private def stream: SoundStream = streamPair.getSync._1
  private def source: SoundSource = streamPair.getSync._2

  eventHandlers += {
    case BrainEvent(event: SoundCardAudioEvent) if !Audio.isDisabled =>
      val samples = SoundSamples(event.data, Settings.get.soundCardSampleRate, SoundSamples.Format.Mono8)
      stream.enqueue(samples)
      source.volume = event.volume
  }

  override def dispose(): Unit = {
    super.dispose()

    for (stream <- streamPair.getOption) {
      stream._2.stop()
    }
  }

  override def fillRmbMenu(menu: ContextMenu): Unit = {
    menu.addEntry(ContextMenuEntry("Open card interface", IconSource.Icons.Window) {
      window.open()
    })

    menu.addSeparator()

    super.fillRmbMenu(menu)
  }

  override def factory: ItemFactory = SoundCardItem.Factory
}

object SoundCardItem {
  object Factory extends ItemFactory {
    override type I = SoundCardItem

    override def itemClass: Class[I] = classOf

    override def name: String = "Sound Card"

    override def tier: Option[Tier] = Some(Tier.Two)

    override def icon: IconSource = IconSource.Items.SoundCard

    override def build(): SoundCardItem = new SoundCardItem(new SoundCard)

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