{-# OPTIONS_HADDOCK hide #-}

module WebDriverPreCore.Internal.Utils
  ( opt,
    txt,
    enumerate,
    -- Aeson utils
    jsonToText,
    lsbToText,
    prettyPrintJson,
    parseJson
  )
where

import Data.Aeson
  ( Key,
    KeyValue ((.=)),
    ToJSON (),
    Value (..), eitherDecodeStrict,
  )
import Data.Function ((.), ($))
import Data.Functor (Functor, (<$>))
import Data.String (String)
import Data.Text ( Text, pack)
import Data.Text.Encoding (encodeUtf8, decodeUtf8)
import GHC.Show (Show (..))
import Data.Aeson.Encode.Pretty (encodePretty)
import Data.ByteString.Lazy qualified as LBS
import Data.Text.IO qualified as T
import Control.Exception (try, Exception (displayException), SomeException)
import GHC.Base (IO)
import Data.Either (Either, either)
import System.IO (print)
import GHC.Enum (Enum, Bounded (..))


{-
  this module is used between the library and testing modules
  it will be removed in a later relaease
-}

txt :: (Show a) => a -> Text
txt :: forall a. Show a => a -> Text
txt = String -> Text
pack (String -> Text) -> (a -> String) -> a -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> String
forall a. Show a => a -> String
show


enumerate :: (Enum a, Bounded a) => [a]
enumerate :: forall a. (Enum a, Bounded a) => [a]
enumerate = [a
forall a. Bounded a => a
minBound ..]

-- Aeson stuff
-- TODO move to separte library

opt :: (Functor f, KeyValue e b, ToJSON a) => Key -> f a -> f b
opt :: forall (f :: * -> *) e b a.
(Functor f, KeyValue e b, ToJSON a) =>
Key -> f a -> f b
opt Key
lbl f a
mb = (Key
lbl Key -> a -> b
forall v. ToJSON v => Key -> v -> b
forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.=) (a -> b) -> f a -> f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> f a
mb

-- https://blog.ssanj.net/posts/2019-09-24-pretty-printing-json-in-haskell.html
lsbToText :: LBS.ByteString -> Text
lsbToText :: ByteString -> Text
lsbToText = ByteString -> Text
decodeUtf8 (ByteString -> Text)
-> (ByteString -> ByteString) -> ByteString -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
LBS.toStrict

jsonToText :: Value -> Text
jsonToText :: Value -> Text
jsonToText = ByteString -> Text
lsbToText (ByteString -> Text) -> (Value -> ByteString) -> Value -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value -> ByteString
forall a. ToJSON a => a -> ByteString
encodePretty

prettyPrintJson :: Value -> IO ()
prettyPrintJson :: Value -> IO ()
prettyPrintJson Value
v = do
  e <- (forall e a. Exception e => IO a -> IO (Either e a)
try @SomeException @_) (IO () -> IO (Either SomeException ()))
-> IO () -> IO (Either SomeException ())
forall a b. (a -> b) -> a -> b
$ Text -> IO ()
T.putStrLn (Value -> Text
jsonToText Value
v)
  either (print . displayException) print e

parseJson :: Text -> Either String Value
parseJson :: Text -> Either String Value
parseJson Text
input =
  ByteString -> Either String Value
forall a. FromJSON a => ByteString -> Either String a
eitherDecodeStrict (Text -> ByteString
encodeUtf8 Text
input)