package ocelot.desktop.ui.widget.statusbar

import ocelot.desktop.color.Color
import ocelot.desktop.geometry.{Padding2D, Size2D}
import ocelot.desktop.graphics.{Graphics, IconSource}
import ocelot.desktop.ui.UiHandler
import ocelot.desktop.ui.event.handlers.{HoverHandler, MouseHandler}
import ocelot.desktop.ui.event.{ClickEvent, MouseEvent}
import ocelot.desktop.ui.layout.{AlignItems, LinearLayout}
import ocelot.desktop.ui.widget._
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
import ocelot.desktop.ui.widget.traits.HoverAnimation
import ocelot.desktop.util.Keybind.FPSCounter
import ocelot.desktop.util.Keymap.Press
import ocelot.desktop.{ColorScheme, OcelotDesktop}

import scala.collection.immutable.ArraySeq
import scala.concurrent.duration.DurationInt


class StatusBar extends Widget {
  override protected val layout: LinearLayout = new LinearLayout(this, alignItems = AlignItems.Center)

  override def minimumSize: Size2D = Size2D(100, 18)
  override def maximumSize: Size2D = Size2D(Float.PositiveInfinity, 18)
  override def receiveMouseEvents = true

  private val keyMouseEntries = new Widget
  private val keyEntries = new Widget
  private var showFPS = false

  eventHandlers += {
    case Press(FPSCounter) =>
      showFPS = !showFPS
      if (showFPS) {
        children :+= new PaddingBox(
          new Label {
            override def maximumSize: Size2D = minimumSize
            override def color: Color = ColorScheme("StatusBarFPS")
            override def text: String = f"FPS: ${UiHandler.fps}%02.1f"
          },
          Padding2D(left = 8, right = 8),
        )
      } else {
        children = children.take(3)
      }
  }

  children :+= new ScrollView(new Widget {
    children :+= keyMouseEntries
    children :+= keyEntries
  }) {
    override def minimumSize: Size2D = inner.minimumSize.copy(width = 5f)
    override def maximumSize: Size2D = inner.minimumSize.copy(width = Float.PositiveInfinity)
    override def hThumbVisible: Boolean = false
  }

  children :+= new HoverBox(new IconButton(
    IconSource.Icons.Pause,
    IconSource.Icons.Play,
    mode = IconButton.Mode.Switch,
    pressedColor = ColorScheme("StatusBarForeground"),
    releasedColor = ColorScheme("StatusBarForeground"),
    tooltip = Some("Pause emulation"),
    model = new IconButton.ReadOnlyModel(() => OcelotDesktop.emulationPaused),
  ) {
    override def onPressed(): Unit = {
      OcelotDesktop.emulationPaused = true
      labelTooltip.foreach(_.setText("Resume emulation"))
    }

    override def onReleased(): Unit = {
      OcelotDesktop.emulationPaused = false
      labelTooltip.foreach(_.setText("Pause emulation"))
    }
  }, Padding2D(left = 2, right = 2))

  children :+= new HoverBox(new Label with MouseHandler with HoverHandler {
    override protected def receiveClickEvents: Boolean = true

    eventHandlers += {
      case ClickEvent(MouseEvent.Button.Left, _) =>
        new ChangeSimulationSpeedDialog().show()

      case ClickEvent(MouseEvent.Button.Right, pos) =>
        val menu = new ContextMenu
        menu.addEntry(
          ContextMenuEntry("Change simulation speed", IconSource.Icons.Edit) {
            new ChangeSimulationSpeedDialog().show()
          }
        )

        menu.addEntry(
          ContextMenuEntry("Reset simulation speed", IconSource.Icons.Restart) {
            OcelotDesktop.ticker.tickInterval = 50.millis
          }
        )

        if (OcelotDesktop.tickerIntervalHistory.nonEmpty)
          menu.addSeparator()

        for (elem <- OcelotDesktop.tickerIntervalHistory.reverseIterator) {
          menu.addEntry(
            ContextMenuEntry((1_000_000f / elem.toMicros).toString) {
              OcelotDesktop.ticker.tickInterval = elem
            }
          )
        }

        root.get.contextMenus.open(menu, pos)
    }

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

      if (mouseOver) {
        root.get.statusBar.addMouseEntry(IconSource.Icons.RMB, "Change simulation speed")
      }
    }

    override def maximumSize: Size2D = minimumSize

    override def color: Color = ColorScheme("StatusBarTPS")

    override def text: String = f"TPS: ${OcelotDesktop.tpsCounter.fps}%02.1f"
  })

  def addMouseEntry(icon: IconSource, text: String): Unit = {
    if (!keyMouseEntries.children.collect({ case e: MouseEntry => e.icon }).contains(icon)) {
      keyMouseEntries.children :+= new MouseEntry(icon, text)
    }
  }

  def addKeyMouseEntry(icon: IconSource, key: String, text: String): Unit = {
    if (!keyMouseEntries.children.collect({ case e: KeyMouseEntry => e }).exists(e => e.icon == icon && e.key == key)) {
      keyMouseEntries.children :+= new KeyMouseEntry(icon, key, text)
    }
  }

  def addKeyEntry(key: String, text: String): Unit = {
    if (!keyEntries.children.map(_.asInstanceOf[KeyEntry]).exists(_.key == key))
      keyEntries.children :+= new KeyEntry(key, text)
  }

  override def draw(g: Graphics): Unit = {
    relayout()
    g.rect(bounds, ColorScheme("StatusBar"))
    g.line(position, position + Size2D(width, 0), 1, ColorScheme("StatusBarBorder"))
    drawChildren(g)
    keyEntries.children = ArraySeq.empty
    keyMouseEntries.children = ArraySeq.empty
  }

  private class HoverBox(widget: Widget, padding: Padding2D = Padding2D(left = 8, right = 8))
    extends PaddingBox(widget, padding)
      with HoverAnimation {

    override def receiveMouseEvents: Boolean = true

    override protected val HoverAnimationColorActive: Color = ColorScheme("StatusBarActive")
    override protected val HoverAnimationColorDefault: Color = HoverAnimationColorActive.toRGBANorm.withAlpha(0)

    override def draw(g: Graphics): Unit = {
      g.rect(bounds, hoverAnimation.color)
      super.draw(g)
    }
  }
}
