module Chiasma.Render where

import Path (Abs, Dir, Path)
import Prettyprinter (line, pretty)

import Chiasma.Codec.Data.Pane (Pane)
import qualified Chiasma.Codec.Data.Window as Codec (Window (Window))
import Chiasma.Data.CodecError (CodecError)
import Chiasma.Data.Ident (Ident, identText)
import Chiasma.Data.Panes (TmuxPanes)
import qualified Chiasma.Data.RenderError as RenderError
import Chiasma.Data.RenderError (RenderError)
import Chiasma.Data.Views (Views)
import Chiasma.Effect.TmuxApi (Tmux)
import Chiasma.Pack (packWindow)
import Chiasma.Session (ensureSession, findOrCreateSession)
import Chiasma.Ui.Data.RenderableTree (RenderableTree)
import Chiasma.Ui.Data.View (ViewTree)
import Chiasma.View (viewsLog)
import Chiasma.Window (ensureView, ensureWindow, findOrCreateWindow, windowState)

renderTree ::
  Members [TmuxPanes Pane, AtomicState Views, Tmux] r =>
  Ident ->
  Codec.Window ->
  RenderableTree ->
  Sem r ()
renderTree :: forall (r :: EffectRow).
Members '[TmuxPanes Pane, AtomicState Views, Tmux] r =>
Ident -> Window -> RenderableTree -> Sem r ()
renderTree Ident
windowIdent Window
window RenderableTree
tree = do
  Doc AnsiStyle -> Sem r ()
forall (r :: EffectRow).
Member (AtomicState Views) r =>
Doc AnsiStyle -> Sem r ()
viewsLog (Doc AnsiStyle -> Sem r ()) -> Doc AnsiStyle -> Sem r ()
forall a b. (a -> b) -> a -> b
$ Text -> Doc AnsiStyle
forall a ann. Pretty a => a -> Doc ann
pretty (Text
"rendering tree in window " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Ident -> Text
identText Ident
windowIdent Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
":") Doc AnsiStyle -> Doc AnsiStyle -> Doc AnsiStyle
forall a. Semigroup a => a -> a -> a
<> Doc AnsiStyle
forall ann. Doc ann
line Doc AnsiStyle -> Doc AnsiStyle -> Doc AnsiStyle
forall a. Semigroup a => a -> a -> a
<> RenderableTree -> Doc AnsiStyle
forall a ann. Pretty a => a -> Doc ann
pretty RenderableTree
tree
  WindowState
wState <- Ident -> Window -> RenderableTree -> Sem r WindowState
forall (r :: EffectRow).
Member (TmuxPanes Pane) r =>
Ident -> Window -> RenderableTree -> Sem r WindowState
windowState Ident
windowIdent Window
window RenderableTree
tree
  WindowState -> Sem r ()
forall (r :: EffectRow).
Members '[AtomicState Views, Tmux] r =>
WindowState -> Sem r ()
packWindow WindowState
wState

render ::
  Members [TmuxPanes Pane !! CodecError, AtomicState Views, Tmux !! CodecError, Stop RenderError] r =>
  Path Abs Dir ->
  Ident ->
  Ident ->
  ViewTree ->
  Sem r ()
render :: forall (r :: EffectRow).
Members
  '[TmuxPanes Pane !! CodecError, AtomicState Views,
    Tmux !! CodecError, Stop RenderError]
  r =>
Path Abs Dir -> Ident -> Ident -> ViewTree -> Sem r ()
render Path Abs Dir
cwd Ident
sessionIdent Ident
windowIdent ViewTree
tree = do
  forall err (eff :: (* -> *) -> * -> *) err' (r :: EffectRow) a.
Members '[Resumable err eff, Stop err'] r =>
(err -> err') -> Sem (eff : r) a -> Sem r a
resumeHoist @_ @(TmuxPanes _) CodecError -> RenderError
RenderError.Codec do
    forall err (eff :: (* -> *) -> * -> *) err' (r :: EffectRow) a.
Members '[Resumable err eff, Stop err'] r =>
(err -> err') -> Sem (eff : r) a -> Sem r a
resumeHoist @_ @Tmux CodecError -> RenderError
RenderError.Codec do
      View SessionId
initialSession <- Ident -> Sem (Tmux : TmuxPanes Pane : r) (View SessionId)
forall (r :: EffectRow).
Member (AtomicState Views) r =>
Ident -> Sem r (View SessionId)
findOrCreateSession Ident
sessionIdent
      View WindowId
initialWindow <- Ident -> Sem (Tmux : TmuxPanes Pane : r) (View WindowId)
forall (r :: EffectRow).
Member (AtomicState Views) r =>
Ident -> Sem r (View WindowId)
findOrCreateWindow Ident
windowIdent
      (SessionId
sid, Maybe WindowId
newSessionWid) <- (LayoutError -> RenderError)
-> Sem
     (Stop LayoutError : Tmux : TmuxPanes Pane : r)
     (SessionId, Maybe WindowId)
-> Sem (Tmux : TmuxPanes Pane : r) (SessionId, Maybe WindowId)
forall e e' (r :: EffectRow) a.
Member (Stop e') r =>
(e -> e') -> Sem (Stop e : r) a -> Sem r a
mapStop LayoutError -> RenderError
RenderError.Layout (View SessionId
-> View WindowId
-> Sem
     (Stop LayoutError : Tmux : TmuxPanes Pane : r)
     (SessionId, Maybe WindowId)
forall (r :: EffectRow).
Members '[AtomicState Views, Tmux, Stop LayoutError] r =>
View SessionId
-> View WindowId -> Sem r (SessionId, Maybe WindowId)
ensureSession View SessionId
initialSession View WindowId
initialWindow)
      window :: Window
window@(Codec.Window WindowId
windowId Int
_ Int
_) <- SessionId
-> View WindowId
-> Maybe WindowId
-> ViewTree
-> Sem (Tmux : TmuxPanes Pane : r) Window
forall (r :: EffectRow).
Members
  '[TmuxPanes Pane, AtomicState Views, Tmux, Stop RenderError] r =>
SessionId
-> View WindowId -> Maybe WindowId -> ViewTree -> Sem r Window
ensureWindow SessionId
sid View WindowId
initialWindow Maybe WindowId
newSessionWid ViewTree
tree
      (RenderableTree -> Sem (Tmux : TmuxPanes Pane : r) ())
-> Maybe RenderableTree -> Sem (Tmux : TmuxPanes Pane : r) ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ (Ident
-> Window -> RenderableTree -> Sem (Tmux : TmuxPanes Pane : r) ()
forall (r :: EffectRow).
Members '[TmuxPanes Pane, AtomicState Views, Tmux] r =>
Ident -> Window -> RenderableTree -> Sem r ()
renderTree Ident
windowIdent Window
window) (Maybe RenderableTree -> Sem (Tmux : TmuxPanes Pane : r) ())
-> Sem (Tmux : TmuxPanes Pane : r) (Maybe RenderableTree)
-> Sem (Tmux : TmuxPanes Pane : r) ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Path Abs Dir
-> WindowId
-> ViewTree
-> Sem (Tmux : TmuxPanes Pane : r) (Maybe RenderableTree)
forall (r :: EffectRow).
Members '[TmuxPanes Pane, AtomicState Views, Tmux] r =>
Path Abs Dir
-> WindowId -> ViewTree -> Sem r (Maybe RenderableTree)
ensureView Path Abs Dir
cwd WindowId
windowId ViewTree
tree