package ocelot.desktop.ui.widget.contextmenu

import ocelot.desktop.ColorScheme
import ocelot.desktop.geometry.{Padding2D, Size2D}
import ocelot.desktop.graphics.Graphics
import ocelot.desktop.ui.layout.{CopyLayout, Layout, LinearLayout}
import ocelot.desktop.ui.widget.{PaddingBox, ScrollView, Widget}
import ocelot.desktop.util.animation.ValueAnimation
import ocelot.desktop.util.animation.easing.EaseInOutQuad
import ocelot.desktop.util.{DrawUtils, Orientation}

import scala.collection.immutable.ArraySeq

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

  private[contextmenu] var isClosing = false
  private[contextmenu] var isOpening = false

  protected var _contextMenus: ContextMenus = _
  protected val alpha = new ValueAnimation(0f, 8f)

  protected val inner: Widget = new Widget {
    override protected val layout = new LinearLayout(this, orientation = Orientation.Vertical)
  }

  private val scrollViewContents = new PaddingBox(inner, Padding2D(top = 4, bottom = 4))

  children :+= new ScrollView(scrollViewContents)

  def preferredSize: Size2D = scrollViewContents.minimumSize

  private[contextmenu] def contextMenus: ContextMenus = _contextMenus

  private[contextmenu] def contextMenus_=(value: ContextMenus): Unit = {
    entries.foreach(_.contextMenus = value)
    _contextMenus = value
  }

  def addEntry(entry: ContextMenuEntry): Unit = {
    entry.contextMenus = contextMenus
    entry.contextMenu = this
    inner.children :+= entry
  }

  def addSeparator(): Unit = {
    inner.children :+= new Separator
  }

  private[contextmenu] def entries: ArraySeq[ContextMenuEntry] = inner.children
    .filter(_.isInstanceOf[ContextMenuEntry])
    .map(_.asInstanceOf[ContextMenuEntry])

  def isClosed: Boolean = {
    alpha.isAt(0f)
  }

  def open(): Unit = {
    isClosing = false
    isOpening = true
    alpha.jump(0.001f)
    alpha.goto(1f)

    var offset = 0.5f
    val step = 0.5f / entries.length.toFloat
    for (entry <- entries) {
      entry.isGhost = false
      entry.textAlpha.jump(offset)
      entry.textAlpha.goto(1f)
      entry.trans.easing = EaseInOutQuad
      entry.trans.jump(-6f + offset * 6f)
      entry.trans.goto(0f)
      offset -= step
    }
  }

  def close(): Unit = {
    isClosing = true
    isOpening = false
    alpha.goto(0f)

    for (entry <- entries) {
      entry.isGhost = true
      entry.textAlpha.goto(1f)
      entry.trans.easing = EaseInOutQuad
      entry.trans.goto(-8f)
    }
  }

  override def draw(g: Graphics): Unit = {
    alpha.update()
    if (alpha.value < 1f) g.beginGroupAlpha() else isOpening = false

    DrawUtils.shadow(g, bounds.x - 8, bounds.y - 8, bounds.w + 16, bounds.h + 20, 0.5f)
    g.rect(bounds, ColorScheme("ContextMenuBackground"))
    DrawUtils.ring(g, bounds.x, bounds.y, bounds.w, bounds.h, 1, ColorScheme("ContextMenuBorder"))

    drawChildren(g)

    if (alpha.value < 1f) g.endGroupAlpha(alpha.value)
  }
}
