module Chiasma.Codec.Query where

import Data.Char (isUpper, toLower)
import qualified Data.Text as Text (concatMap, singleton)
import GHC.Generics (C1, D1, S1, Selector, selName, (:*:))

class TmuxDataQuery f where
  dataQuery :: [Text]

instance TmuxDataQuery f => (TmuxDataQuery (D1 c f)) where
  dataQuery :: [Text]
dataQuery = forall {k} (f :: k). TmuxDataQuery f => [Text]
forall (f :: k -> *). TmuxDataQuery f => [Text]
dataQuery @f

instance TmuxDataQuery f => (TmuxDataQuery (C1 c f)) where
  dataQuery :: [Text]
dataQuery = forall {k} (f :: k). TmuxDataQuery f => [Text]
forall (f :: k -> *). TmuxDataQuery f => [Text]
dataQuery @f

instance (TmuxDataQuery f, TmuxDataQuery g) => TmuxDataQuery (f :*: g) where
  dataQuery :: [Text]
dataQuery = forall {k} (f :: k). TmuxDataQuery f => [Text]
forall (f :: k -> *). TmuxDataQuery f => [Text]
dataQuery @f [Text] -> [Text] -> [Text]
forall a. Semigroup a => a -> a -> a
<> forall {k} (f :: k). TmuxDataQuery f => [Text]
forall (f :: k -> *). TmuxDataQuery f => [Text]
dataQuery @g

trans :: Char -> Text
trans :: Char -> Text
trans Char
a | Char -> Bool
isUpper Char
a = forall a. ToText a => a -> Text
toText @String [Char
Item String
'_', Char -> Char
toLower Char
a]
trans Char
a = Char -> Text
Text.singleton Char
a

snakeCase :: Text -> Text
snakeCase :: Text -> Text
snakeCase =
  (Char -> Text) -> Text -> Text
Text.concatMap Char -> Text
trans

formatQuery :: Text -> Text
formatQuery :: Text -> Text
formatQuery Text
q = Text
"#{" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
snakeCase Text
q Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"}"

instance Selector s => (TmuxDataQuery (S1 s f)) where
  dataQuery :: [Text]
dataQuery =
    [Text -> Text
formatQuery (String -> Text
forall a. ToText a => a -> Text
toText String
query)]
    where
      query :: String
query = Any s f Any -> String
forall {k} (s :: k) k1 (t :: k -> (k1 -> *) -> k1 -> *)
       (f :: k1 -> *) (a :: k1).
Selector s =>
t s f a -> String
forall k1 (t :: Meta -> (k1 -> *) -> k1 -> *) (f :: k1 -> *)
       (a :: k1).
t s f a -> String
selName (t s f p
forall {k} {t :: Meta -> (k -> *) -> k -> *} {p :: k}. t s f p
forall a. HasCallStack => a
undefined :: t s f p)