package nova.monadic_sfx.implicits import monix.execution.Scheduler import monix.reactive.Observable import monix.reactive.Observer import monix.{eval => me} class ActionObservableExecutor[T]( private val delegate: Observable[T] ) extends AnyVal { def -->(sub: Observer[T])(implicit s: Scheduler) = delegate .doOnNext(el => me.Task(sub.onNext(el))) .subscribe() } class ActionObservableBuilder[A]( private val observableAction: Observable[A] ) extends AnyVal { def useLazyEval[T](v: => me.Task[T]) = new ActionObservableExecutor[T](observableAction.mapEval(_ => v)) def useEval[T](cb: A => me.Task[T]) = new ActionObservableExecutor[T]( observableAction.mapEval(cb) ) def useIterableEval[T](cb: A => collection.immutable.Iterable[T]) = new ActionObservableExecutor[T]( observableAction.flatMap(a => Observable.suspend(Observable.fromIterable(cb(a))) ) ) def doOnNext(cb: A => me.Task[Unit]): ActionObservableBuilder[A] = new ActionObservableBuilder(observableAction.doOnNext(cb)) def mapEval[B](cb: A => me.Task[B]) = new ActionObservableBuilder(observableAction.mapEval(cb)) def underlying = observableAction // def publish[B](f: Observable[A] => Observable[B]) = // new ActionObservableBuilder(observableAction.publishSelector(f)) def useEval2[B, C](f: A => me.Task[B], g: A => me.Task[C]) = new ActionObservableExecutor[(B, C)]( observableAction.publishSelector(conn => conn .mapEval(f) .switchMap(b => conn.mapEval(a => for { c <- g(a) } yield (b, c) ) ) ) ) def bifurcate[B, C]( f: ActionObservableBuilder[A] => B, g: ActionObservableBuilder[A] => C )(implicit s: Scheduler) = observableAction .publishSelector(conn => Observable( Observable.unit.doOnNext(_ => me.Task(f(new ActionObservableBuilder[A](conn))) >> me.Task.unit ), Observable.unit.doOnNext(_ => me.Task(g(new ActionObservableBuilder[A](conn))) >> me.Task.unit ) ).merge ) .subscribe() // def useEval2[B,C](a1: ActionObservableBuilder[A] => B, a2: ActionObservableBuilder[A] => C) = observableAction.publishSelector(conn => // new ActionObservableBuilder[] // ) } // class MappedActionExecutor(actionMap: Map[])