module OpenAI.Prelude
    ( -- * JSON
      aesonOptions
    , stripPrefix
    , labelModifier

      -- * Multipart Form Data
    , input
    , renderIntegral
    , renderRealFloat
    , getExtension

      -- * Re-exports
    , module Data.Aeson
    , module Data.ByteString.Lazy
    , module Data.List.NonEmpty
    , module Data.Map
    , module Data.String
    , module Data.Text
    , module Data.Time.Clock.POSIX
    , module Data.Vector
    , module Data.Void
    , module Data.Word
    , module GHC.Generics
    , module Numeric.Natural
    , module Servant.API
    , module Servant.Multipart.API
    , module Web.HttpApiData
    ) where

import Data.ByteString.Lazy (ByteString)
import Data.List.NonEmpty (NonEmpty(..))
import Data.Map (Map)
import Data.Text (Text)
import Data.Time.Clock.POSIX (POSIXTime)
import Data.Vector (Vector)
import Data.Void (Void)
import GHC.Generics (Generic)
import Data.String (IsString(..))
import Data.Word (Word8)
import Numeric.Natural (Natural)
import Web.HttpApiData (ToHttpApiData(..))

import Data.Aeson
    ( FromJSON(..)
    , ToJSON(..)
    , Options(..)
    , SumEncoding(..)
    , Value(..)
    , genericParseJSON
    , genericToJSON
    )
import Servant.API
    ( Accept(..)
    , Capture
    , Delete
    , Get
    , Header'
    , JSON
    , MimeUnrender(..)
    , OctetStream
    , Post
    , QueryParam
    , ReqBody
    , Required
    , Strict
    , (:<|>)(..)
    , (:>)
    )
import Servant.Multipart.API
    ( FileData(..)
    , Input(..)
    , MultipartData(..)
    , MultipartForm
    , ToMultipart(..)
    , Tmp
    )

import qualified Data.Aeson as Aeson
import qualified Data.Char as Char
import qualified Data.List as List
import qualified Data.Text as Text
import qualified Data.Text.Lazy as Text.Lazy
import qualified Data.Text.Lazy.Builder as Builder
import qualified Data.Text.Lazy.Builder.RealFloat as RealFloat
import qualified Data.Text.Lazy.Builder.Int as Int
import qualified System.FilePath as FilePath

dropTrailingUnderscore :: String -> String
dropTrailingUnderscore :: String -> String
dropTrailingUnderscore String
"_" = String
""
dropTrailingUnderscore String
""  = String
""
dropTrailingUnderscore (Char
c : String
cs) = Char
c Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
dropTrailingUnderscore String
cs

labelModifier :: String -> String
labelModifier :: String -> String
labelModifier = (Char -> Char) -> String -> String
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
Char.toLower (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
dropTrailingUnderscore

stripPrefix :: String -> String -> String
stripPrefix :: String -> String -> String
stripPrefix String
prefix String
string = String -> String
labelModifier String
suffix
  where
    suffix :: String
suffix = case String -> String -> Maybe String
forall a. Eq a => [a] -> [a] -> Maybe [a]
List.stripPrefix String
prefix String
string of
        Maybe String
Nothing -> String
string
        Just String
x  -> String
x

aesonOptions :: Options
aesonOptions :: Options
aesonOptions = Options
Aeson.defaultOptions
    { fieldLabelModifier = labelModifier
    , constructorTagModifier = labelModifier
    , omitNothingFields = True
    }

input :: Text -> Text -> [ Input ]
input :: Text -> Text -> [Input]
input Text
iName Text
iValue = [ Input{Text
iName :: Text
iValue :: Text
iName :: Text
iValue :: Text
..} ]

renderIntegral :: Integral number => number -> Text
renderIntegral :: forall number. Integral number => number -> Text
renderIntegral number
number = Text -> Text
Text.Lazy.toStrict (Builder -> Text
Builder.toLazyText Builder
builder)
  where
    builder :: Builder
builder = number -> Builder
forall a. Integral a => a -> Builder
Int.decimal number
number

renderRealFloat :: RealFloat number => number -> Text
renderRealFloat :: forall number. RealFloat number => number -> Text
renderRealFloat number
number = Text -> Text
Text.Lazy.toStrict (Builder -> Text
Builder.toLazyText Builder
builder)
  where
    builder :: Builder
builder = FPFormat -> Maybe Int -> number -> Builder
forall a. RealFloat a => FPFormat -> Maybe Int -> a -> Builder
RealFloat.formatRealFloat FPFormat
RealFloat.Fixed Maybe Int
forall a. Maybe a
Nothing number
number

getExtension :: FilePath -> Text
getExtension :: String -> Text
getExtension String
file = String -> Text
Text.pack (Int -> String -> String
forall a. Int -> [a] -> [a]
drop Int
1 (String -> String
FilePath.takeExtension String
file))