package ocelot.desktop.ui.widget.window

import ocelot.desktop.geometry.Vector2D
import ocelot.desktop.ui.layout.Layout
import ocelot.desktop.ui.widget.Widget

import scala.collection.immutable.ArraySeq

class WindowPool extends Widget {
  override protected val layout: Layout = new Layout(this)

  private def windows: ArraySeq[Window] = children.map(_.asInstanceOf[Window])

  private def windows_=(newWindows: ArraySeq[Window]): Unit = children = newWindows

  private[window] def addWindow(window: Window): Unit = {
    if (windows.contains(window)) return
    windows :+= window

    updateFocus()
  }

  private[window] def removeWindow(window: Window): Unit = {
    val idx = windows.indexOf(window)
    if (idx == -1) return
    windows = windows.patch(idx, Nil, 1)

    updateFocus()
  }

  private[window] def focusWindow(window: Window): Unit = {
    if (!windows.contains(window)) return

    // move window to the end
    val idx = windows.indexWhere(_ == window)
    windows = windows.patch(idx, Nil, 1) :+ window

    updateFocus()
  }

  private[window] def unfocusWindow(window: Window): Unit = {
    if (!windows.contains(window)) return

    if (windows.length >= 2 && window == windows.last) {
      // swap two last windows
      windows = windows.init.init :+ window :+ windows.init.last
    }

    updateFocus()
  }

  private[window] def recoverLoadedWindow(window: Window): Unit = {
    if (window.isClosed) return

    val index = window.poolIndex
    if (index == -1) {
      windows :+= window
      return
    }

    if (index > windows.size) {
      // windows are loaded in random order, so fill missing indices with placeholders
      while (index > windows.size) {
        windows :+= new PlaceholderWindow
      }

      windows :+= window
    } else if (windows(window.poolIndex).isInstanceOf[PlaceholderWindow]) {
      windows = windows.patch(index, Some(window), 1)
    } else {
      // this shouldn't happen unless save file is messed up
      windows :+= window
    }
  }

  private def updateFocus(): Unit = {
    if (windows.isEmpty) return
    windows.init.foreach(_.setUnfocused())
    windows.last.setFocused()

    windows.zipWithIndex.foreach { case (window, index) => window.poolIndex = index }
  }

  def refreshWindows(): Unit = {
    windows.foreach(_.refresh())
  }

  def movePinnedWindows(delta: Vector2D): Unit = {
    windows.filter(_.isPinned).foreach(_.position += delta)
  }

  def deleteAllWindows(): Unit = {
    windows.foreach(_.dispose())
    windows = ArraySeq.empty
  }

  private class PlaceholderWindow extends Window
}
