package wow.doge.mygame.implicits

import javafx.scene.{input => jfxsi}
import javafx.{event => jfxe}
import monix.execution.Ack
import monix.execution.Cancelable
import monix.reactive.Observable
import monix.reactive.OverflowStrategy
import scalafx.scene.Scene
import scalafx.scene.control.ButtonBase

object JavaFXMonixObservables {

  implicit final class SceneObservables(private val scene: Scene)
      extends AnyVal {
    def observableMousePressed(): Observable[jfxsi.MouseEvent] = {
      import monix.execution.cancelables.SingleAssignCancelable
      Observable.create(OverflowStrategy.Unbounded) { sub =>
        val c = SingleAssignCancelable()
        val l = new jfxe.EventHandler[jfxsi.MouseEvent] {
          override def handle(event: jfxsi.MouseEvent): Unit = {
            if (sub.onNext(event) == Ack.Stop) c.cancel()
          }
        }

        scene.onMousePressed = l
        c := Cancelable(() =>
          scene.removeEventHandler(
            jfxsi.MouseEvent.MOUSE_PRESSED,
            l
          )
        )
        c
      }
    }
    def observableMouseDragged(): Observable[jfxsi.MouseEvent] = {
      import monix.execution.cancelables.SingleAssignCancelable
      Observable.create(OverflowStrategy.Unbounded) { sub =>
        val c = SingleAssignCancelable()
        val l = new jfxe.EventHandler[jfxsi.MouseEvent] {
          override def handle(event: jfxsi.MouseEvent): Unit = {
            if (sub.onNext(event) == Ack.Stop) c.cancel()
          }
        }

        scene.onMouseDragged = l
        c := Cancelable(() =>
          scene.removeEventHandler(
            jfxsi.MouseEvent.MOUSE_DRAGGED,
            l
          )
        )
        c
      }
    }
  }

  implicit final class OnActionObservable(
      private val button: ButtonBase
  ) extends AnyVal {
    def observableAction(): Observable[jfxe.ActionEvent] = {
      import monix.execution.cancelables.SingleAssignCancelable
      Observable.create(OverflowStrategy.Unbounded) { sub =>
        val c = SingleAssignCancelable()
        val l = new jfxe.EventHandler[jfxe.ActionEvent] {
          override def handle(event: jfxe.ActionEvent): Unit = {
            if (sub.onNext(event) == Ack.Stop) c.cancel()
          }
        }

        button.onAction = l
        c := Cancelable(() =>
          button.removeEventHandler(
            jfxe.ActionEvent.ACTION,
            l
          )
        )
        c
      }
    }
  }
}
