module Chiasma.Command.Window where

import Exon (exon)
import Path (Abs, Dir, Path)

import Chiasma.Codec.Data.Pane (Pane)
import Chiasma.Codec.Data.Window (Window (Window))
import Chiasma.Data.Ident (Ident)
import Chiasma.Data.LayoutError (LayoutError (LayoutError))
import qualified Chiasma.Data.Target as Target
import Chiasma.Data.TmuxCommand (TmuxCommand (ListWindows, NewWindow, SplitWindow))
import Chiasma.Data.TmuxId (SessionId, WindowId)
import Chiasma.Data.WindowParams (cwd, detach, name, target)
import qualified Chiasma.Data.WindowSelection as WindowSelection
import qualified Chiasma.Effect.TmuxApi as Tmux
import Chiasma.Effect.TmuxApi (Tmux)

sameId :: WindowId -> Window -> Bool
sameId :: WindowId -> Window -> Bool
sameId WindowId
target (Window WindowId
i Int
_ Int
_) = WindowId
target WindowId -> WindowId -> Bool
forall a. Eq a => a -> a -> Bool
== WindowId
i

windows ::
  Member Tmux r =>
  Sem r [Window]
windows :: forall (r :: EffectRow). Member Tmux r => Sem r [Window]
windows =
  TmuxCommand [Window] -> Sem r [Window]
forall (command :: * -> *) (r :: EffectRow) a.
Member (TmuxApi command) r =>
command a -> Sem r a
Tmux.send (WindowSelection -> TmuxCommand [Window]
ListWindows WindowSelection
WindowSelection.All)

window ::
  Member Tmux r =>
  WindowId ->
  Sem r (Maybe Window)
window :: forall (r :: EffectRow).
Member Tmux r =>
WindowId -> Sem r (Maybe Window)
window WindowId
windowId =
  (Window -> Bool) -> [Window] -> Maybe Window
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find (WindowId -> Window -> Bool
sameId WindowId
windowId) ([Window] -> Maybe Window)
-> Sem r [Window] -> Sem r (Maybe Window)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Sem r [Window]
forall (r :: EffectRow). Member Tmux r => Sem r [Window]
windows

sessionWindows ::
  Member Tmux r =>
  SessionId ->
  Sem r [Window]
sessionWindows :: forall (r :: EffectRow).
Member Tmux r =>
SessionId -> Sem r [Window]
sessionWindows SessionId
sid =
  TmuxCommand [Window] -> Sem r [Window]
forall (command :: * -> *) (r :: EffectRow) a.
Member (TmuxApi command) r =>
command a -> Sem r a
Tmux.send (WindowSelection -> TmuxCommand [Window]
ListWindows (Target -> WindowSelection
WindowSelection.InSession (SessionId -> Target
Target.Session SessionId
sid)))

-- TODO this could be ListWindow
newSessionWindow ::
  Members [Tmux, Stop LayoutError] r =>
  SessionId ->
  Sem r Window
newSessionWindow :: forall (r :: EffectRow).
Members '[Tmux, Stop LayoutError] r =>
SessionId -> Sem r Window
newSessionWindow SessionId
sid =
  SessionId -> Sem r [Window]
forall (r :: EffectRow).
Member Tmux r =>
SessionId -> Sem r [Window]
sessionWindows SessionId
sid Sem r [Window] -> ([Window] -> Sem r Window) -> Sem r Window
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
    [Item [Window]
w] -> Window -> Sem r Window
forall (f :: * -> *) a. Applicative f => a -> f a
pure Item [Window]
Window
w
    [Window]
ws -> LayoutError -> Sem r Window
forall e (r :: EffectRow) a. Member (Stop e) r => e -> Sem r a
stop (Text -> LayoutError
LayoutError [exon|New session contains multiple windows: #{show ws}|])

doesWindowExist ::
  Member Tmux r =>
  WindowId ->
  Sem r Bool
doesWindowExist :: forall (r :: EffectRow). Member Tmux r => WindowId -> Sem r Bool
doesWindowExist WindowId
windowId =
  (Window -> Bool) -> [Window] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (WindowId -> Window -> Bool
sameId WindowId
windowId) ([Window] -> Bool) -> Sem r [Window] -> Sem r Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Sem r [Window]
forall (r :: EffectRow). Member Tmux r => Sem r [Window]
windows

newWindow ::
  Member Tmux r =>
  SessionId ->
  Ident ->
  Sem r Window
newWindow :: forall (r :: EffectRow).
Member Tmux r =>
SessionId -> Ident -> Sem r Window
newWindow SessionId
sid Ident
name =
  TmuxCommand Window -> Sem r Window
forall (command :: * -> *) (r :: EffectRow) a.
Member (TmuxApi command) r =>
command a -> Sem r a
Tmux.send (WindowParams -> TmuxCommand Window
NewWindow WindowParams
forall a. Default a => a
def { $sel:target:WindowParams :: Target
target = SessionId -> Target
Target.Session SessionId
sid, $sel:name:WindowParams :: Maybe Ident
name = Ident -> Maybe Ident
forall a. a -> Maybe a
Just Ident
name })

splitWindowInDir ::
  Member Tmux r =>
  Path Abs Dir ->
  WindowId ->
  Sem r Pane
splitWindowInDir :: forall (r :: EffectRow).
Member Tmux r =>
Path Abs Dir -> WindowId -> Sem r Pane
splitWindowInDir Path Abs Dir
dir WindowId
windowId =
  TmuxCommand Pane -> Sem r Pane
forall (command :: * -> *) (r :: EffectRow) a.
Member (TmuxApi command) r =>
command a -> Sem r a
Tmux.send (WindowParams -> SplitWindowParams -> TmuxCommand Pane
SplitWindow WindowParams
forall a. Default a => a
def { $sel:target:WindowParams :: Target
target = WindowId -> Target
Target.Window WindowId
windowId, $sel:detach:WindowParams :: Bool
detach = Bool
True, $sel:cwd:WindowParams :: Maybe (Path Abs Dir)
cwd = Path Abs Dir -> Maybe (Path Abs Dir)
forall a. a -> Maybe a
Just Path Abs Dir
dir } SplitWindowParams
forall a. Default a => a
def)

splitWindow ::
  Member Tmux r =>
  WindowId ->
  Sem r Pane
splitWindow :: forall (r :: EffectRow). Member Tmux r => WindowId -> Sem r Pane
splitWindow WindowId
windowId =
  TmuxCommand Pane -> Sem r Pane
forall (command :: * -> *) (r :: EffectRow) a.
Member (TmuxApi command) r =>
command a -> Sem r a
Tmux.send (WindowParams -> SplitWindowParams -> TmuxCommand Pane
SplitWindow WindowParams
forall a. Default a => a
def { $sel:target:WindowParams :: Target
target = WindowId -> Target
Target.Window WindowId
windowId, $sel:detach:WindowParams :: Bool
detach = Bool
True } SplitWindowParams
forall a. Default a => a
def)