package wow.doge.mygame.launcher import cats.effect.Resource import cats.effect.concurrent.Deferred import cats.kernel.Eq import javafx.application.Platform import javafx.beans.value.ObservableValue import monix.bio.Task import monix.catnap.CancelableF import monix.execution.CancelablePromise import monix.reactive.Observable import monix.{eval => me} import scalafx.Includes._ import scalafx.application.JFXApp import scalafx.application.JFXApp.PrimaryStage import scalafx.beans.property.StringProperty import scalafx.scene.control.Button import scalafx.stage.StageStyle import wow.doge.mygame.executors.Schedulers import wow.doge.mygame.implicits.JavaFXMonixObservables._ import wow.doge.mygame.utils.IOUtils._ object Launcher { sealed trait LauncherResult object LauncherResult { case object LaunchGame extends LauncherResult case object Exit extends LauncherResult implicit val eqForLR = Eq.fromUniversalEquals[LauncherResult] } class Props( val schedulers: Schedulers, val signal: Deferred[Task, LauncherResult] ) { val create = Task(new Launcher(this)) } } class Launcher private (props: Launcher.Props) { import Launcher._ private lazy val launchButton = new Button { text = "Launch" } private lazy val launchAction = launchButton .observableAction() .doOnNext(_ => toTask(props.signal.complete(LauncherResult.LaunchGame))) def testChangeObs( obs: Observable[(ObservableValue[_ <: String], String, String)] ) = obs .doOnNext { case (x, y, z) => monix.eval.Task.unit } // .subscribe() private lazy val exitButton = new Button { text = "Exit" // text <-- testChangeObs } // exitButton.text.bind StringProperty("") addListener ((_, _, _) => ()) private lazy val exitAction = exitButton .observableAction() .doOnNext(_ => toTask(props.signal.complete(LauncherResult.Exit))) private lazy val _scene = DefaultUI.scene(launchButton, exitButton) private lazy val _stage = new PrimaryStage { scene = _scene } private def internal(startSignal: CancelablePromise[Unit]) = new JFXApp { stage = _stage stage.initStyle(StageStyle.Undecorated) // ResizeHelper.addResizeListener(stage) startSignal.success(()) } private lazy val sceneDragObservable = { val mpo = _scene.observableMousePressed() val mdo = _scene.observableMouseDragged() mpo.concatMap(pressEvent => mdo.doOnNext(dragEvent => me.Task(pprint.log("emitted")) >> me.Task( _stage.setX(dragEvent.screenX - pressEvent.sceneX) ) >> me.Task( _stage.setY( dragEvent.screenY - pressEvent.sceneY ) ) ) ) } // import cats.syntax.all._ // def init(delay: FiniteDuration = 2000.millis) = // for { // _ <- Task(Platform.setImplicitExit(false)) // x <- (Task.unit.start, Task.unit.start).parTupled // fxAppStartFib <- Task(internal.main(Array.empty)).start // _ <- Task.sleep(500.millis) // sceneDragFib <- toIO(sceneDragObservable.completedL).start // buttonActionsComposedFib <- toIO( // Observable(launchAction, exitAction).merge // .doOnNext(_ => // me.Task(internal.stage.close()).executeOn(props.schedulers.fx) // ) // .completedL // ).start // c <- CancelableF[Task]( // fxAppStartFib.cancel >> buttonActionsComposedFib.cancel >> sceneDragFib.cancel // ) // } yield (c) def init = Resource.make(for { _ <- Task(Platform.setImplicitExit(false)) startSignal <- Task(CancelablePromise[Unit]()) delegate <- Task(internal(startSignal)) combinedFib <- Task .parZip2( Task(delegate.main(Array.empty)), Task.fromCancelablePromise(startSignal) >> toIO( me.Task.parSequence( List( sceneDragObservable.completedL, Observable(launchAction, exitAction).merge .doOnNext(_ => me.Task(delegate.stage.close()) .executeOn(props.schedulers.fx) ) .completedL ) ) ) ) .start c <- CancelableF[Task]( // Task(println("Cancelling")) >> // combinedFib.cancel >> // fxAppStartFib.cancel // Task.unit combinedFib.cancel ) } yield c)(_.cancel) }