{-|
Module      : Gargantext.Core.AsyncUpdates.CentralExchange.Types
Description : Types for asynchronous notifications (central exchange)
Copyright   : (c) CNRS, 2017-Present
License     : AGPL + CECILL v3
Maintainer  : team@gargantext.org
Stability   : experimental
Portability : POSIX

https://gitlab.iscpif.fr/gargantext/haskell-gargantext/issues/341

Docs:
https://dev.sub.gargantext.org/#/share/Notes/187918    
-}

module Gargantext.Core.AsyncUpdates.CentralExchange.Types where

import Codec.Binary.UTF8.String qualified as CBUTF8
import Data.Aeson ((.:), (.=), object, withObject)
import Data.Aeson qualified as Aeson
import Data.Aeson.Types (prependFailure, typeMismatch)
import Data.ByteString.Lazy qualified as BSL
import Gargantext.API.Admin.Orchestrator.Types (JobLog)
import Gargantext.Core.Types (NodeId)
import Gargantext.Prelude
import Prelude qualified
import Servant.Job.Core (Safety(Safe))
import Servant.Job.Types (JobStatus)
    
{-

Central exchange is a service, which gathers messages from various
places and informs the Dispatcher (which will then inform users about
various events).
    
-}

-- INTERNAL MESSAGES
data CEMessage =
    UpdateJobProgress (JobStatus 'Safe JobLog)
  | UpdateTreeFirstLevel NodeId
instance Prelude.Show CEMessage where
  show (UpdateJobProgress js) = "UpdateJobProgress " <> (CBUTF8.decode $ BSL.unpack $ Aeson.encode js)
  show (UpdateTreeFirstLevel nodeId) = "UpdateTreeFirstLevel " <> show nodeId
instance FromJSON CEMessage where
  parseJSON = withObject "CEMessage" $ \o -> do
    type_ <- o .: "type"
    case type_ of
      "update_job_progress" -> do
        js <- o .: "js"
        pure $ UpdateJobProgress js
      "update_tree_first_level" -> do
        node_id <- o .: "node_id"
        pure $ UpdateTreeFirstLevel node_id
      s -> prependFailure "parsing type failed, " (typeMismatch "type" s)
instance ToJSON CEMessage where
  toJSON (UpdateJobProgress js) = object [
        "type" .= toJSON ("update_job_progress" :: Text)
      , "js"   .= toJSON js
    ]
  toJSON (UpdateTreeFirstLevel node_id) = object [
      "type"    .= toJSON ("update_tree_first_level" :: Text)
    , "node_id" .= toJSON node_id
    ]


class HasCentralExchangeNotification env where
  ce_notify :: (MonadReader env m, MonadBase IO m) => CEMessage -> m ()
