{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DeriveGeneric #-}

module Gargantext.API.Routes.Named.Viz (
  -- * Routes types
    PhyloAPI(..)
  , GetPhylo(..)
  , PostPhylo(..)
  , GraphAPI(..)
  , GraphAsyncAPI(..)
  , GraphVersionsAPI(..)

  -- * API types (appears in the routes)
  , PhyloData(..)
  , GraphVersions(..)
  ) where

import Data.Aeson
import Data.Swagger
import Data.Text (Text)
import GHC.Generics
import Gargantext.API.Admin.Orchestrator.Types ( JobLog )
import Gargantext.Core.Types
import Gargantext.Core.Types.Phylo
import Gargantext.Core.Viz.Graph.Types
import Gargantext.Core.Viz.LegacyPhylo (Level)
import Gargantext.Core.Viz.Phylo
import Gargantext.Core.Viz.Phylo.Legacy.LegacyMain (MinSizeBranch)
import Prelude
import Servant
import Servant.Job.Async (AsyncJobsAPI)
import Servant.XML.Conduit (XML)
import Test.QuickCheck


data PhyloAPI mode = PhyloAPI
  { getPhyloEp  :: mode :- Summary "Phylo API" :> NamedRoutes GetPhylo
  , postPhyloEp :: mode :- NamedRoutes PostPhylo
  } deriving Generic


newtype GetPhylo mode = GetPhylo
  { getPhyloDataEp :: mode :- QueryParam "listId"      ListId
                           :> QueryParam "level"       Level
                           :> QueryParam "minSizeBranch" MinSizeBranch
                           :> Get '[JSON] PhyloData
  } deriving Generic


newtype PostPhylo mode = PostPhylo
  { postPhyloByListIdEp :: mode :- QueryParam "listId" ListId :> (Post '[JSON] NodeId)
  } deriving Generic


data GraphAPI mode = GraphAPI
  { getGraphEp       :: mode :- Get '[JSON] HyperdataGraphAPI
  , getGraphAsyncEp  :: mode :- "async" :> NamedRoutes GraphAsyncAPI
  , cloneGraphEp     :: mode :- "clone" :> ReqBody '[JSON] HyperdataGraphAPI :> Post '[JSON] NodeId
  , gexfEp           :: mode :- "gexf" :> Get '[XML] (Headers '[Servant.Header "Content-Disposition" Text] Graph)
  , graphVersionsAPI :: mode :- "versions" :> NamedRoutes GraphVersionsAPI
  } deriving Generic


newtype GraphAsyncAPI mode = GraphAsyncAPI
  { recomputeGraphEp :: mode :- Summary "Recompute graph"
                             :> "recompute"
                             :> AsyncJobsAPI JobLog () JobLog
  } deriving Generic


data GraphVersionsAPI mode = GraphVersionsAPI
  { getGraphVersionsEp :: mode :- Summary "Graph versions" :> Get '[JSON] GraphVersions
  , recomputeGraphVersionEp :: mode :- Summary "Recompute graph version" :> Post '[JSON] Graph
  } deriving Generic


data PhyloData = PhyloData { pd_corpusId :: NodeId
                           , pd_listId   :: NodeId
                           , pd_data     :: GraphData
                           , pd_config   :: PhyloConfig
                           }
  deriving (Generic, Show, Eq)


data GraphVersions = GraphVersions
  { gv_graph :: Maybe Int
  , gv_repo  :: Int
  } deriving (Show, Generic)


--
-- instances
--

instance ToJSON PhyloData where
  toJSON PhyloData{..} =
    object [
      "pd_corpusId" .= toJSON pd_corpusId
    , "pd_listId"   .= toJSON pd_listId
    , "pd_data"     .= toJSON pd_data
    , "pd_config"   .= toJSON pd_config
    ]

instance FromJSON PhyloData where
  parseJSON = withObject "PhyloData" $ \o -> do
    pd_corpusId <- o .: "pd_corpusId"
    pd_listId   <- o .: "pd_listId"
    pd_data     <- o .: "pd_data"
    pd_config   <- o .: "pd_config"
    pure $ PhyloData{..}

instance Arbitrary PhyloData where
  arbitrary = PhyloData <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary

instance ToSchema PhyloData

instance FromJSON GraphVersions

instance ToJSON GraphVersions

instance ToSchema GraphVersions

