package ocelot.desktop.ui.widget.contextmenu

import ocelot.desktop.geometry.Vector2D
import ocelot.desktop.graphics.Graphics
import ocelot.desktop.ui.UiHandler
import ocelot.desktop.ui.event.{KeyEvent, MouseEvent}
import ocelot.desktop.ui.layout.Layout
import ocelot.desktop.ui.widget.Widget
import org.lwjgl.input.Keyboard

import scala.collection.immutable.ArraySeq

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

  private var ghost: Option[ContextMenuEntry] = None

  private def menus: ArraySeq[ContextMenu] = children.map(_.asInstanceOf[ContextMenu])

  private[contextmenu] def setGhost(g: ContextMenuEntry): Unit = {
    ghost = Some(g)
  }

  override def receiveAllMouseEvents: Boolean = true

  eventHandlers += {
    case KeyEvent(KeyEvent.State.Press, Keyboard.KEY_ESCAPE, _) =>
      closeAll()

    case MouseEvent(MouseEvent.State.Press, _) =>
      if (!menus.map(_.bounds).exists(_.contains(UiHandler.mousePosition))) closeAll()
  }

  def open(menu: ContextMenu,
           openPos: Vector2D = UiHandler.mousePosition,
           isSubmenu: Boolean = false): Unit =
  {
    open(menu, openPos, openPos.x, openPos.y, isSubmenu)
  }

  def open(menu: ContextMenu,
           openPos: Vector2D,
           xFlipPos: Float,
           yFlipPos: Float,
           isSubmenu: Boolean): Unit =
  {
    if (children.contains(menu)) return
    if (menu.entries.isEmpty) return
    if (!isSubmenu) for (child <- menus) close(child)

    menu.recalculateBounds()
    menu.size = menu.minimumSize

    val size = menu.size
    var pos = openPos

    if (pos.x + size.width > width)
      pos = pos.setX(xFlipPos - size.width)
    if (pos.y + size.height > height)
      pos = pos.setY(yFlipPos - size.height)

    menu.position = pos

    menu.contextMenus = this
    menu.open()
    children :+= menu
  }

  def close(menu: ContextMenu): Unit = {
    menu.close()
  }

  def closeAll(): Unit = {
    for (child <- menus) close(child)
  }

  override def draw(g: Graphics): Unit = {
    super.draw(g)
    if (ghost.isDefined && ghost.get.alpha.isAt(0f)) ghost = None
    ghost.foreach(_.draw(g))
  }

  override def update(): Unit = {
    super.update()
    children = children.filterNot(_.asInstanceOf[ContextMenu].isClosed)
  }
}
