{-# LANGUAGE ScopedTypeVariables  #-}
{-# LANGUAGE TypeApplications     #-}
{-# LANGUAGE TypeOperators        #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Gargantext.API.Server.Named.EKG where

import Data.HashMap.Strict as HM
import Data.Text as T
import Data.Text.IO as T
import Data.Time.Clock.POSIX (getPOSIXTime)
import Gargantext.API.Routes.Named.EKG
import Network.Wai
import Protolude
import Servant
import Servant.Auth
import Servant.Ekg
import Servant.Server.Generic
import System.Metrics
import System.Metrics.Json qualified as J


ekgServer :: FilePath -> Store -> EkgAPI AsServer
ekgServer assetsDir store = EkgAPI
  { ekgAPI = (getAll :<|> getOne) :<|> serveDirectoryFileServer assetsDir }

  where getAll = J.Sample <$> liftIO (sampleAll store)
        getOne segments = do
          let metric = T.intercalate "." segments
          metrics <- liftIO (sampleAll store)
          maybe (liftIO (T.putStrLn "not found boohoo") >> throwError err404) (return . J.Value) (HM.lookup metric metrics)


newEkgStore :: HasEndpoint api => Proxy api -> IO (Store, Middleware)
newEkgStore api = do
  s <- newStore
  registerGcMetrics s
  registerCounter "ekg.server_timestamp_ms" getTimeMs s -- used by UI
  mid <- monitorEndpoints api s
  pure (s, mid)

  where getTimeMs = (round . (* 1000)) `fmap` getPOSIXTime

instance HasEndpoint api => HasEndpoint (Auth xs a :> api) where
    getEndpoint        _ = getEndpoint        (Proxy :: Proxy api)
    enumerateEndpoints _ = enumerateEndpoints (Proxy :: Proxy api)

instance HasEndpoint (ToServant api AsApi) => HasEndpoint (NamedRoutes api) where
    getEndpoint        _ = getEndpoint        (Proxy @(ToServant api AsApi))
    enumerateEndpoints _ = enumerateEndpoints (Proxy @(ToServant api AsApi))
