module Chiasma.Codec where

import Chiasma.Data.TmuxId (PaneId, SessionId, WindowId)
import qualified Data.Text as Text (drop, dropEnd, splitOn, take, takeEnd, unwords)
import GHC.Generics (Rep, to)

import Chiasma.Codec.Decode (TmuxDataDecode(..), TmuxDecodeError(TooManyFields))
import Chiasma.Codec.Query (TmuxDataQuery(..))

newtype TmuxQuery =
  TmuxQuery { TmuxQuery -> Text
unQ :: Text }
  deriving (TmuxQuery -> TmuxQuery -> Bool
(TmuxQuery -> TmuxQuery -> Bool)
-> (TmuxQuery -> TmuxQuery -> Bool) -> Eq TmuxQuery
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TmuxQuery -> TmuxQuery -> Bool
$c/= :: TmuxQuery -> TmuxQuery -> Bool
== :: TmuxQuery -> TmuxQuery -> Bool
$c== :: TmuxQuery -> TmuxQuery -> Bool
Eq, Int -> TmuxQuery -> ShowS
[TmuxQuery] -> ShowS
TmuxQuery -> String
(Int -> TmuxQuery -> ShowS)
-> (TmuxQuery -> String)
-> ([TmuxQuery] -> ShowS)
-> Show TmuxQuery
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TmuxQuery] -> ShowS
$cshowList :: [TmuxQuery] -> ShowS
show :: TmuxQuery -> String
$cshow :: TmuxQuery -> String
showsPrec :: Int -> TmuxQuery -> ShowS
$cshowsPrec :: Int -> TmuxQuery -> ShowS
Show)

genDecode :: (Generic a, TmuxDataDecode (Rep a)) => Text -> Either TmuxDecodeError a
genDecode :: Text -> Either TmuxDecodeError a
genDecode Text
fields = do
  ([Text]
rest, Rep a Any
result) <- [Text] -> Either TmuxDecodeError ([Text], Rep a Any)
forall k (f :: k -> *) (a :: k).
TmuxDataDecode f =>
[Text] -> Either TmuxDecodeError ([Text], f a)
decode' (Text -> Text -> [Text]
Text.splitOn Text
" " (Text -> [Text]) -> (Text -> Text) -> Text -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
trim (Text -> [Text]) -> Text -> [Text]
forall a b. (a -> b) -> a -> b
$ Text
fields)
  case [Text]
rest of
    [] -> a -> Either TmuxDecodeError a
forall (m :: * -> *) a. Monad m => a -> m a
return (a -> Either TmuxDecodeError a) -> a -> Either TmuxDecodeError a
forall a b. (a -> b) -> a -> b
$ Rep a Any -> a
forall a x. Generic a => Rep a x -> a
to Rep a Any
result
    [Text]
a -> TmuxDecodeError -> Either TmuxDecodeError a
forall a b. a -> Either a b
Left (TmuxDecodeError -> Either TmuxDecodeError a)
-> TmuxDecodeError -> Either TmuxDecodeError a
forall a b. (a -> b) -> a -> b
$ [Text] -> TmuxDecodeError
TooManyFields [Text]
a
  where
    trim :: Text -> Text
trim Text
text =
      if Int -> Text -> Text
Text.take Int
1 Text
text Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
" " Bool -> Bool -> Bool
&& Int -> Text -> Text
Text.takeEnd Int
1 Text
text Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
" "
      then Int -> Text -> Text
Text.drop Int
1 (Text -> Text) -> (Text -> Text) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Text -> Text
Text.dropEnd Int
1 (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ Text
text
      else Text
text

class TmuxCodec a where
    decode :: Text -> Either TmuxDecodeError a
    default decode :: (Generic a, TmuxDataDecode (Rep a)) => Text -> Either TmuxDecodeError a
    decode = Text -> Either TmuxDecodeError a
forall a.
(Generic a, TmuxDataDecode (Rep a)) =>
Text -> Either TmuxDecodeError a
genDecode

    query :: TmuxQuery
    default query :: TmuxDataQuery (Rep a) => TmuxQuery
    query = Text -> TmuxQuery
TmuxQuery (Text -> TmuxQuery) -> Text -> TmuxQuery
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
Text.unwords ([Text] -> Text) -> [Text] -> Text
forall a b. (a -> b) -> a -> b
$ TmuxDataQuery (Rep a) => [Text]
forall k (f :: k). TmuxDataQuery f => [Text]
query' @(Rep a)

instance TmuxCodec SessionId
instance TmuxCodec WindowId
instance TmuxCodec PaneId