packages feed

firestore-0.1.0.0: src/Database/Firestore/Internal.hs

module Database.Firestore.Internal where

import Control.Applicative (Applicative (liftA2))
import Control.Lens
import Control.Monad (join, msum)
import Data.Maybe (fromMaybe)
import Database.Firestore.Types
import qualified Network.Google.FireStore as FireStore

-- | This module is for the interaction with `gogol` stuff.

-- | There's a bug in gogol-firestore currently, apparently... that makes "nulls" slightly ambiguous. https://github.com/brendanhay/gogol/issues/170)
parseValue :: FireStore.Value -> Value
parseValue v =
  fromMaybe
    -- (Unknown $ Text.pack $ show v)
    Null
    $ msum
      [ liftA2 GeoPoint (join $ v ^? (FireStore.vGeoPointValue . _Just . FireStore.llLatitude)) (join $ v ^? (FireStore.vGeoPointValue . _Just . FireStore.llLongitude)),
        Bytes <$> v ^. FireStore.vBytesValue,
        Int . fromIntegral <$> v ^. FireStore.vIntegerValue,
        Timestamp <$> v ^. FireStore.vTimestampValue,
        Double <$> v ^. FireStore.vDoubleValue,
        String <$> v ^. FireStore.vStringValue,
        Bool <$> v ^. FireStore.vBooleanValue,
        Map . fmap parseValue
          <$> v ^? (FireStore.vMapValue . _Just . FireStore.mvFields . _Just . FireStore.mvfAddtional),
        Array . map parseValue <$> v ^? (FireStore.vArrayValue . _Just . FireStore.avValues),
        Reference <$> v ^. FireStore.vReferenceValue,
        Null <$ v ^. FireStore.vNullValue
      ]

buildValue :: Value -> FireStore.Value
buildValue v =
  FireStore.value
    & FireStore.vGeoPointValue
      .~ ( ( \(lat, lng) ->
               FireStore.latLng
                 & FireStore.llLatitude ?~ lat
                 & FireStore.llLongitude ?~ lng
           )
             <$> v
             ^? _GeoPoint
         )
    & FireStore.vBytesValue .~ (v ^? _Bytes)
    & FireStore.vIntegerValue .~ (fromIntegral <$> v ^? _Int)
    & FireStore.vTimestampValue .~ (v ^? _Timestamp)
    & FireStore.vDoubleValue .~ (v ^? _Double)
    & FireStore.vStringValue .~ (v ^? _String)
    & FireStore.vBooleanValue .~ (v ^? _Bool)
    & FireStore.vMapValue
      .~ ( (\v -> FireStore.mapValue & FireStore.mvFields ?~ FireStore.mapValueFields v) . fmap buildValue <$> v ^? _Map
         )
    & FireStore.vArrayValue .~ ((\v -> FireStore.arrayValue & FireStore.avValues .~ v) . map buildValue <$> v ^? _Array)
    & FireStore.vReferenceValue .~ (v ^? _Reference)
    & FireStore.vNullValue .~ (FireStore.NullValue <$ v ^? _Null)

parseDocument :: FireStore.Document -> Document
parseDocument d =
  Document
    (d ^. FireStore.dName)
    (d ^. FireStore.dCreateTime)
    (d ^. FireStore.dUpdateTime)
    (parseValue <$> d ^. FireStore.dFields . _Just . FireStore.dfAddtional)

buildDocument :: Document -> FireStore.Document
buildDocument (Document {name, fields}) =
  FireStore.document
    & FireStore.dName .~ name
    & FireStore.dFields
      ?~ ( FireStore.documentFields (fmap buildValue fields)
         )