{-|
Module      : Gargantext.Core.Notifications.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.Notifications.CentralExchange.Types where

import Data.Aeson ((.:), (.=), object, withObject)
import Data.Aeson.Types (prependFailure, typeMismatch)
import Gargantext.API.Admin.Orchestrator.Types (JobLog)
import Gargantext.Core.Types (NodeId)
import Gargantext.Core.Worker.Types (JobInfo)
import Gargantext.Database.Admin.Types.Node (UserId)
import Gargantext.Prelude
import Prelude qualified
    
{-

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 =
    -- | New-style jobs (async worker).
    --   Please note that (I think) all jobs are associated with some NodeId
    --   (providing a nodeId allows us to discover new jobs on the frontend).
  -- | UpdateWorkerProgress JobInfo NodeId JobLog
    UpdateWorkerProgress JobInfo JobLog
    -- | Update tree for given nodeId
  | UpdateTreeFirstLevel NodeId
  | NotifyUser UserId Text
  | Ping
instance Prelude.Show CEMessage where
  -- show (UpdateWorkerProgress ji nodeId jl) = "UpdateWorkerProgress " <> show ji <> " " <> show nodeId <> " " <> show jl
  show (UpdateWorkerProgress ji jl) = "UpdateWorkerProgress " <> show ji <> " " <> show jl
  show (UpdateTreeFirstLevel nodeId) = "UpdateTreeFirstLevel " <> show nodeId
  show (NotifyUser userId msg) = "NotifyUser " <> show userId <> ", " <> show msg
  show Ping = "Ping"
instance FromJSON CEMessage where
  parseJSON = withObject "CEMessage" $ \o -> do
    type_ <- o .: "type"
    case type_ of
      "update_worker_progress" -> do
        ji <- o .: "ji"
        jl <- o .: "jl"
        -- nodeId <- o .: "node_id"
        -- pure $ UpdateWorkerProgress ji nodeId jl
        pure $ UpdateWorkerProgress ji jl
      "update_tree_first_level" -> do
        node_id <- o .: "node_id"
        pure $ UpdateTreeFirstLevel node_id
      "notify_user" -> do
        user_id <- o .: "user_id"
        msg <- o .: "message"
        pure $ NotifyUser user_id msg
      "ping" -> pure Ping
      s -> prependFailure "parsing type failed, " (typeMismatch "type" s)
instance ToJSON CEMessage where
  toJSON (UpdateWorkerProgress ji jl) = object [
        "type"    .= ("update_worker_progress" :: Text)
      , "ji"      .= ji
      , "jl"      .= jl
      -- , "node_id" .= toJSON nodeId
    ]
  toJSON (UpdateTreeFirstLevel nodeId) = object [
      "type"    .= ("update_tree_first_level" :: Text)
    , "node_id" .= nodeId
    ]
  toJSON (NotifyUser userId msg) = object [
      "type"    .= ("notify_user" :: Text)
    , "user_id" .= userId
    , "message" .= msg
    ]
  toJSON Ping = object [ "type" .= ("ping" :: Text) ]


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

