{-# LANGUAGE DeriveGeneric #-}

-- |
-- Module      : Docs.TextElement
-- Description : Contents of a Text Node
-- License     : AGPL-3
-- Maintainer  : stu235271@mail.uni-kiel.de
--               stu236925@mail.uni-kiel.de
--
-- This module contains the definitions for the contents of a documen trees text
-- nodes.
module Docs.TextElement
    ( TextElementID (..)
    , TextElement (..)
    , TextElementKind
    , TextElementType
    , TextElementRef (..)
    , prettyPrintTextElementRef
    ) where

import Data.Proxy (Proxy (..))
import Data.Text (Text)

import GHC.Generics (Generic)
import GHC.Int (Int64)

import Control.Lens ((&), (?~))
import Data.Aeson (FromJSON (..), ToJSON (..))
import Data.OpenApi
    ( OpenApiType (..)
    , ToParamSchema (..)
    , ToSchema (..)
    , exclusiveMinimum
    , minimum_
    , type_
    )
import Web.HttpApiData (FromHttpApiData (..))

import Docs.Document (DocumentID (..))
import Docs.Hash (Hashable (..))

-- | ID for a text element
newtype TextElementID = TextElementID
    { TextElementID -> Int64
unTextElementID :: Int64
    }
    deriving (TextElementID -> TextElementID -> Bool
(TextElementID -> TextElementID -> Bool)
-> (TextElementID -> TextElementID -> Bool) -> Eq TextElementID
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: TextElementID -> TextElementID -> Bool
== :: TextElementID -> TextElementID -> Bool
$c/= :: TextElementID -> TextElementID -> Bool
/= :: TextElementID -> TextElementID -> Bool
Eq, Eq TextElementID
Eq TextElementID =>
(TextElementID -> TextElementID -> Ordering)
-> (TextElementID -> TextElementID -> Bool)
-> (TextElementID -> TextElementID -> Bool)
-> (TextElementID -> TextElementID -> Bool)
-> (TextElementID -> TextElementID -> Bool)
-> (TextElementID -> TextElementID -> TextElementID)
-> (TextElementID -> TextElementID -> TextElementID)
-> Ord TextElementID
TextElementID -> TextElementID -> Bool
TextElementID -> TextElementID -> Ordering
TextElementID -> TextElementID -> TextElementID
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: TextElementID -> TextElementID -> Ordering
compare :: TextElementID -> TextElementID -> Ordering
$c< :: TextElementID -> TextElementID -> Bool
< :: TextElementID -> TextElementID -> Bool
$c<= :: TextElementID -> TextElementID -> Bool
<= :: TextElementID -> TextElementID -> Bool
$c> :: TextElementID -> TextElementID -> Bool
> :: TextElementID -> TextElementID -> Bool
$c>= :: TextElementID -> TextElementID -> Bool
>= :: TextElementID -> TextElementID -> Bool
$cmax :: TextElementID -> TextElementID -> TextElementID
max :: TextElementID -> TextElementID -> TextElementID
$cmin :: TextElementID -> TextElementID -> TextElementID
min :: TextElementID -> TextElementID -> TextElementID
Ord, Int -> TextElementID -> ShowS
[TextElementID] -> ShowS
TextElementID -> String
(Int -> TextElementID -> ShowS)
-> (TextElementID -> String)
-> ([TextElementID] -> ShowS)
-> Show TextElementID
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> TextElementID -> ShowS
showsPrec :: Int -> TextElementID -> ShowS
$cshow :: TextElementID -> String
show :: TextElementID -> String
$cshowList :: [TextElementID] -> ShowS
showList :: [TextElementID] -> ShowS
Show)

instance Hashable TextElementID where
    updateHash :: Ctx -> TextElementID -> Ctx
updateHash Ctx
ctx = Ctx -> Int64 -> Ctx
forall a. Hashable a => Ctx -> a -> Ctx
updateHash Ctx
ctx (Int64 -> Ctx) -> (TextElementID -> Int64) -> TextElementID -> Ctx
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TextElementID -> Int64
unTextElementID

instance ToJSON TextElementID where
    toJSON :: TextElementID -> Value
toJSON = Int64 -> Value
forall a. ToJSON a => a -> Value
toJSON (Int64 -> Value)
-> (TextElementID -> Int64) -> TextElementID -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TextElementID -> Int64
unTextElementID

instance FromJSON TextElementID where
    parseJSON :: Value -> Parser TextElementID
parseJSON = (Int64 -> TextElementID) -> Parser Int64 -> Parser TextElementID
forall a b. (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Int64 -> TextElementID
TextElementID (Parser Int64 -> Parser TextElementID)
-> (Value -> Parser Int64) -> Value -> Parser TextElementID
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value -> Parser Int64
forall a. FromJSON a => Value -> Parser a
parseJSON

instance ToSchema TextElementID where
    declareNamedSchema :: Proxy TextElementID -> Declare (Definitions Schema) NamedSchema
declareNamedSchema Proxy TextElementID
_ = Proxy Int64 -> Declare (Definitions Schema) NamedSchema
forall a.
ToSchema a =>
Proxy a -> Declare (Definitions Schema) NamedSchema
declareNamedSchema (Proxy Int64
forall {k} (t :: k). Proxy t
Proxy :: Proxy Int64)

instance ToParamSchema TextElementID where
    toParamSchema :: Proxy TextElementID -> Schema
toParamSchema Proxy TextElementID
_ =
        Schema
forall a. Monoid a => a
mempty
            Schema -> (Schema -> Schema) -> Schema
forall a b. a -> (a -> b) -> b
& (Maybe OpenApiType -> Identity (Maybe OpenApiType))
-> Schema -> Identity Schema
forall s a. HasType s a => Lens' s a
Lens' Schema (Maybe OpenApiType)
type_ ((Maybe OpenApiType -> Identity (Maybe OpenApiType))
 -> Schema -> Identity Schema)
-> OpenApiType -> Schema -> Schema
forall s t a b. ASetter s t a (Maybe b) -> b -> s -> t
?~ OpenApiType
OpenApiInteger
            Schema -> (Schema -> Schema) -> Schema
forall a b. a -> (a -> b) -> b
& (Maybe Scientific -> Identity (Maybe Scientific))
-> Schema -> Identity Schema
forall s a. HasMinimum s a => Lens' s a
Lens' Schema (Maybe Scientific)
minimum_ ((Maybe Scientific -> Identity (Maybe Scientific))
 -> Schema -> Identity Schema)
-> Scientific -> Schema -> Schema
forall s t a b. ASetter s t a (Maybe b) -> b -> s -> t
?~ Scientific
0
            Schema -> (Schema -> Schema) -> Schema
forall a b. a -> (a -> b) -> b
& (Maybe Bool -> Identity (Maybe Bool)) -> Schema -> Identity Schema
forall s a. HasExclusiveMinimum s a => Lens' s a
Lens' Schema (Maybe Bool)
exclusiveMinimum ((Maybe Bool -> Identity (Maybe Bool))
 -> Schema -> Identity Schema)
-> Bool -> Schema -> Schema
forall s t a b. ASetter s t a (Maybe b) -> b -> s -> t
?~ Bool
False

instance FromHttpApiData TextElementID where
    parseUrlPiece :: Text -> Either Text TextElementID
parseUrlPiece = (Int64 -> TextElementID
TextElementID (Int64 -> TextElementID)
-> Either Text Int64 -> Either Text TextElementID
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>) (Either Text Int64 -> Either Text TextElementID)
-> (Text -> Either Text Int64) -> Text -> Either Text TextElementID
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Either Text Int64
forall a. FromHttpApiData a => Text -> Either Text a
parseUrlPiece

-- | Scoped identifier for a text element
data TextElementRef = TextElementRef
    { TextElementRef -> DocumentID
documentID :: DocumentID
    , TextElementRef -> TextElementID
textElementID :: TextElementID
    }
    deriving (TextElementRef -> TextElementRef -> Bool
(TextElementRef -> TextElementRef -> Bool)
-> (TextElementRef -> TextElementRef -> Bool) -> Eq TextElementRef
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: TextElementRef -> TextElementRef -> Bool
== :: TextElementRef -> TextElementRef -> Bool
$c/= :: TextElementRef -> TextElementRef -> Bool
/= :: TextElementRef -> TextElementRef -> Bool
Eq, (forall x. TextElementRef -> Rep TextElementRef x)
-> (forall x. Rep TextElementRef x -> TextElementRef)
-> Generic TextElementRef
forall x. Rep TextElementRef x -> TextElementRef
forall x. TextElementRef -> Rep TextElementRef x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. TextElementRef -> Rep TextElementRef x
from :: forall x. TextElementRef -> Rep TextElementRef x
$cto :: forall x. Rep TextElementRef x -> TextElementRef
to :: forall x. Rep TextElementRef x -> TextElementRef
Generic)

prettyPrintTextElementRef :: TextElementRef -> String
prettyPrintTextElementRef :: TextElementRef -> String
prettyPrintTextElementRef TextElementRef
ref =
    Int64 -> String
forall a. Show a => a -> String
show (DocumentID -> Int64
unDocumentID (TextElementRef -> DocumentID
documentID TextElementRef
ref))
        String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"."
        String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int64 -> String
forall a. Show a => a -> String
show (TextElementID -> Int64
unTextElementID (TextElementRef -> TextElementID
textElementID TextElementRef
ref))

instance ToJSON TextElementRef

instance FromJSON TextElementRef

instance ToSchema TextElementRef

type TextElementKind = Text

type TextElementType = Text

-- | Contains metadata about a text element.
data TextElement = TextElement
    { TextElement -> TextElementID
identifier :: TextElementID
    , TextElement -> Text
textElementKind :: TextElementKind
    , TextElement -> Text
textElementType :: TextElementType
    }
    deriving ((forall x. TextElement -> Rep TextElement x)
-> (forall x. Rep TextElement x -> TextElement)
-> Generic TextElement
forall x. Rep TextElement x -> TextElement
forall x. TextElement -> Rep TextElement x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. TextElement -> Rep TextElement x
from :: forall x. TextElement -> Rep TextElement x
$cto :: forall x. Rep TextElement x -> TextElement
to :: forall x. Rep TextElement x -> TextElement
Generic)

instance ToJSON TextElement

instance FromJSON TextElement

instance ToSchema TextElement