{-|
Module      : Gargantext.API.Routes.Named.Private
Description :
Copyright   : (c) CNRS, 2017
License     : AGPL + CECILL v3
Maintainer  : team@gargantext.org
Stability   : experimental
Portability : POSIX
-}

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}

module Gargantext.API.Routes.Named.Private (
  -- * Routes types
    GargPrivateAPI(..)
  , MkProtectedAPI
  , GargPrivateAPI'(..)
  , GargAdminAPI(..)
  , NodeAPIEndpoint(..)
  , MembersAPI(..)
  , AnnuaireAPIEndpoint(..)
  , CorpusAPIEndpoint(..)
  ) where


import Data.Text (Text)
import Gargantext.API.Admin.Auth.Types (AuthenticatedUser)
import Gargantext.API.Auth.PolicyCheck (PolicyChecked)
import Gargantext.API.Routes.Named.Contact (ContactAPI)
import Gargantext.API.Routes.Named.Context (ContextAPI)
import Gargantext.API.Routes.Named.Corpus (AddWithTempFile, AddWithQuery, CorpusExportAPI, MakeSubcorpusAPI)
import Gargantext.API.Routes.Named.Count (CountAPI, Query)
import Gargantext.API.Routes.Named.Document (DocumentExportAPI)
import Gargantext.API.Routes.Named.List (GETAPI, JSONAPI, TSVAPI)
import Gargantext.API.Routes.Named.Node
import Gargantext.API.Routes.Named.Remote
import Gargantext.API.Routes.Named.Share
import Gargantext.API.Routes.Named.Table
import Gargantext.API.Routes.Named.Tree
import Gargantext.API.Routes.Named.Viz
import Gargantext.Database.Admin.Types.Hyperdata.Any
import Gargantext.Database.Admin.Types.Hyperdata.Corpus
import Gargantext.Database.Admin.Types.Node
import GHC.Generics
import Servant.API
import Servant.Auth qualified as SA


type MkProtectedAPI private = SA.Auth '[SA.JWT, SA.Cookie] AuthenticatedUser :> private


newtype GargPrivateAPI mode = GargPrivateAPI
  { mkPrivateAPI :: mode :- MkProtectedAPI (NamedRoutes GargPrivateAPI')
  } deriving Generic


data GargPrivateAPI' mode = GargPrivateAPI'
  { gargAdminAPI :: mode :- NamedRoutes GargAdminAPI
  , nodeEp       :: mode :- NamedRoutes NodeAPIEndpoint
  , contextEp    :: mode :- "context"  :> Summary "Context endpoint"
                                       :> Capture "node_id" ContextId
                                       :> NamedRoutes (ContextAPI HyperdataAny)
  , corpusNodeAPI :: mode :- NamedRoutes CorpusAPIEndpoint
  , corpusNodeNodeAPI :: mode :- "corpus" :> Summary "Corpus endpoint"
                                          :> Capture "node1_id" NodeId
                                          :> "document"
                                          :> Capture "node2_id" NodeId
                                          :> NamedRoutes (NodeNodeAPI HyperdataAny)
  , corpusExportAPI :: mode :- "corpus" :> Capture "node_id" CorpusId
                                        :> NamedRoutes CorpusExportAPI
  , annuaireEp :: mode :- NamedRoutes AnnuaireAPIEndpoint
  , contactAPI :: mode :- "annuaire" :> Summary "Contact endpoint"
                                     :> Capture "annuaire_id" NodeId
                                     :> NamedRoutes ContactAPI
  , tableNgramsAPI :: mode :- "document" :> Summary "Document endpoint"
                                         :> Capture "doc_id" DocId
                                         :> "ngrams"
                                         :> NamedRoutes TableNgramsAPI
  , documentExportAPI :: mode :- "texts" :> Capture "node_id" DocId
                                         :> NamedRoutes DocumentExportAPI
  , phyloExportAPI    :: mode :- "phylo" :> Capture "node_id" DocId
                                         :> NamedRoutes PhyloExportAPI
  , countAPI :: mode :- "count" :> Summary "Count endpoint"
                                :> ReqBody '[JSON] Query
                                :> NamedRoutes CountAPI
  , graphAPI :: mode :- "graph" :> Summary "Graph endpoint"
                                :> Capture "graph_id" NodeId
                                :> NamedRoutes GraphAPI
  , treeAPI :: mode :- "tree" :> Summary "Tree endpoint"
                              :> Capture "tree_id" NodeId
                              :> PolicyChecked (NamedRoutes NodeTreeAPI)
  , treeFlatAPI :: mode :- "treeflat" :> Summary "Flat tree endpoint"
                                      :> Capture "tree_id" NodeId
                                      :> NamedRoutes TreeFlatAPI
  , membersAPI       :: mode :- "members" :> Summary "Team node members" :> NamedRoutes MembersAPI
  , addWithTempFile  :: mode :- NamedRoutes AddWithTempFile
  , addWithQueryEp   :: mode :- NamedRoutes AddWithQuery
  , makeSubcorpusAPI :: mode :- NamedRoutes MakeSubcorpusAPI
  , listGetAPI       :: mode :- NamedRoutes GETAPI
  , listJsonAPI      :: mode :- NamedRoutes JSONAPI
  , listTsvAPI       :: mode :- NamedRoutes TSVAPI
  , shareUrlAPI      :: mode :- "shareurl" :> NamedRoutes ShareURL
  } deriving Generic


data GargAdminAPI mode = GargAdminAPI
  { rootsEp       :: mode :- "user"  :> Summary "First user endpoint" :> NamedRoutes Roots
  , adminNodesAPI :: mode :- "nodes" :> Summary "Nodes endpoint"
                                     :> ReqBody '[JSON] [NodeId]
                                     :> NamedRoutes NodesAPI
  } deriving Generic

-- | The 'Node' API, unlike the ones for annuaire and corpus,
-- have other endpoints which should not be shared in the hierarchy,
-- like the /freeze/ one. Similarly, a 'Corpus' API will have a
-- '/publish' endpoint that doesn't generalise to everything.
data NodeAPIEndpoint mode = NodeAPIEndpoint
  { nodeEndpointAPI :: mode :- "node"
                            :> Summary "Node endpoint"
                            :> Capture "node_id" NodeId
                            :> NamedRoutes (NodeAPI HyperdataAny)
  , nodeRemoteImportAPI :: mode :- "node" :> "remote" :> NamedRoutes RemoteImportAPI
  } deriving Generic

newtype AnnuaireAPIEndpoint mode = AnnuaireAPIEndpoint
  { annuaireEndpointAPI :: mode :- "annuaire"
                        :> Summary "Annuaire endpoint"
                        :> Capture "annuaire_id" NodeId
                        :> NamedRoutes (NodeAPI HyperdataAnnuaire)
  } deriving Generic

newtype CorpusAPIEndpoint mode = CorpusAPIEndpoint
  { corpusEndpointAPI :: mode :- "corpus"
                      :> Summary "Corpus endpoint"
                      :> Capture "corpus_id" NodeId
                      :> NamedRoutes (NodeAPI HyperdataCorpus)
  } deriving Generic

newtype MembersAPI mode = MembersAPI
  { getMembersEp :: mode :- Get '[JSON] [Text]
  } deriving Generic

