package ocelot.desktop.ui.widget.window

import ocelot.desktop.util.{Disposable, Persistable}
import totoro.ocelot.brain.nbt.NBTTagCompound

trait Windowed[T <: Window] extends Persistable with Disposable {
  protected def createWindow(): T

  private var _window: Option[T] = None

  final def windowCreated: Boolean = _window.nonEmpty

  def closeWindow(): Unit = _window.foreach(_.close())

  def closeAndDisposeWindow(): Unit = {
    for (window <- _window) {
      window.closeAndDispose()
      _window = None
    }
  }

  final def window: T = _window match {
    case Some(window) => window

    case None =>
      val window = createWindow()
      if (windowNbt.isDefined) {
        window.load(windowNbt.get)
      }

      _window = Some(window)

      window
  }

  override def dispose(): Unit = {
    super.dispose()
    closeAndDisposeWindow()
  }
  // ------------------------------- NBT -------------------------------

  protected def windowNBTKey: String = "window"

  private var windowNbt: Option[NBTTagCompound] = None

  override def load(nbt: NBTTagCompound): Unit = {
    super.load(nbt)

    if (nbt.hasKey(windowNBTKey)) {
      windowNbt = Some(nbt.getCompoundTag(windowNBTKey))

      // If window was open on last save - we should
      // create it's instance & bring back to screen
      Window.State(windowNbt.get.getInteger("state")) match {
        case Window.State.Opening | Window.State.Open =>
          window.open()
        case _ =>
      }
    }
  }

  override def save(nbt: NBTTagCompound): Unit = {
    super.save(nbt)

    // Reusing tag if it was defined (may be useful for disposing
    // purposes in further implementations)
    if (windowCreated) {
      val tag = windowNbt.getOrElse(new NBTTagCompound())
      window.save(tag)
      windowNbt = Some(tag)
    }

    // Window instance may not be created, but tag may be loaded
    if (windowNbt.isDefined)
      nbt.setTag(windowNBTKey, windowNbt.get)
  }
}
