content: {-# LANGUAGE DataKinds #-}
  {-# LANGUAGE DuplicateRecordFields #-}
  {-# LANGUAGE RecordWildCards #-}
  
  -- | A module for the types used in the external API.
  -- Breaking changes to these require alternations to the share frontend.
  module Share.Web.Share.Comments.Types where
  
  import Data.Aeson
  import Share.Prelude
  import Share.Web.Share.Comments (CommentEvent (..), RevisionNumber)
  import Share.Web.Share.DisplayInfo.Types (UserDisplayInfo)
  
  data CreateCommentRequest = CreateCommentRequest
    { content :: Text
    }
    deriving (Show)
  
  instance ToJSON CreateCommentRequest where
    toJSON CreateCommentRequest {..} =
      object
        [ "content" .= content
        ]
  
  instance FromJSON CreateCommentRequest where
    parseJSON = withObject "CreateCommentRequest" \o -> do
      content <- o .: "content"
      pure CreateCommentRequest {..}
  
  data UpdateCommentRequest = UpdateCommentRequest
    { content :: Text,
      -- The revision number of the comment that the update was based on.
      -- This is used to determine if the comment has been updated since the
      -- client last fetched it.
      expectedRevision :: RevisionNumber
    }
    deriving (Show)
  
  instance ToJSON UpdateCommentRequest where
    toJSON UpdateCommentRequest {..} =
      object
        [ "content" .= content,
          "expectedRevision" .= expectedRevision
        ]
  
  instance FromJSON UpdateCommentRequest where
    parseJSON = withObject "UpdateCommentRequest" \o -> do
      content <- o .: "content"
      expectedRevision <- o .: "expectedRevision"
      pure UpdateCommentRequest {..}
  
  data UpdateCommentResponse
    = UpdateCommentSuccess (CommentEvent UserDisplayInfo)
    | UpdateCommentConflict (CommentEvent UserDisplayInfo)
    deriving (Show)
  
  instance ToJSON UpdateCommentResponse where
    toJSON = \case
      UpdateCommentSuccess event -> object ["kind" .= ("success" :: Text), "comment" .= event]
      UpdateCommentConflict event -> object ["kind" .= ("conflict" :: Text), "comment" .= event]
  
  instance FromJSON UpdateCommentResponse where
    parseJSON = withObject "UpdateCommentResponse" \o -> do
      kind :: Text <- o .: "kind"
      case kind of
        "success" -> UpdateCommentSuccess <$> o .: "comment"
        "conflict" -> UpdateCommentConflict <$> o .: "comment"
        _ -> fail $ "Unknown kind: " <> show kind
  