{-|
Module      : Import.hs
Description : Gargantext Import Corpus
Copyright   : (c) CNRS, 2017-Present
License     : AGPL + CECILL v3
Maintainer  : team@gargantext.org
Stability   : experimental
Portability : POSIX

Import a corpus binary.

 -}

{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE Strict            #-}
{-# LANGUAGE TypeOperators #-}

module CLI.Import where

import CLI.Parsers
import CLI.Types
import Control.Monad.Catch (MonadCatch)
import Gargantext.API.Admin.EnvTypes (DevEnv(..), DevJobHandle(..))
import Gargantext.API.Dev (withDevEnv, runCmdGargDev)
import Gargantext.API.Errors.Types ( BackendInternalError )
import Gargantext.API.Node () -- instances
import Gargantext.Core (Lang(..))
import Gargantext.Core.Text.Corpus.Parsers (FileFormat(..), FileType(..))
import Gargantext.Core.Types.Individu (User(..))
import Gargantext.Database.Action.Flow (flowCorpusFile, flowAnnuaire, TermType(..))
import Gargantext.Database.Action.Flow.Types (FlowCmdM)
import Gargantext.Database.Admin.Types.Node (CorpusId)
import Gargantext.Database.Query.Tree.Root (MkCorpusUser(MkCorpusUserNormalCorpusName))
import Gargantext.Prelude
import Gargantext.Utils.Jobs.Monad ( MonadJobStatus(..) )
import Options.Applicative
import Prelude (String)
import qualified Data.Text as T


importCLI :: ImportArgs -> IO ()
importCLI (ImportArgs fun user name settingsPath corpusPath) = do
  let
    tt     = Multi EN
    format = TsvGargV3
    corpus :: forall m. (FlowCmdM DevEnv BackendInternalError m, MonadJobStatus m, MonadCatch m, JobHandle m ~ DevJobHandle) => m CorpusId
    mkCorpusUser = MkCorpusUserNormalCorpusName (UserName $ cs user) (cs name :: Text)
    corpus = flowCorpusFile mkCorpusUser tt  format Plain corpusPath Nothing DevJobHandle

    corpusTsvHal :: forall m. (FlowCmdM DevEnv BackendInternalError m, MonadJobStatus m, MonadCatch m, JobHandle m ~ DevJobHandle) => m CorpusId
    corpusTsvHal = flowCorpusFile mkCorpusUser tt TsvHal Plain corpusPath Nothing DevJobHandle

    annuaire :: forall m. (FlowCmdM DevEnv BackendInternalError m, MonadJobStatus m, MonadCatch m, JobHandle m ~ DevJobHandle) => m CorpusId
    annuaire = flowAnnuaire (MkCorpusUserNormalCorpusName (UserName $ cs user) "Annuaire") (Multi EN) corpusPath DevJobHandle

  withDevEnv settingsPath $ \env -> do
    void $ case fun of
      IF_corpus
        -> runCmdGargDev env corpus
      IF_corpusTsvHal
        -> runCmdGargDev env corpusTsvHal
      IF_annuaire
        -> runCmdGargDev env annuaire

importCmd :: HasCallStack => Mod CommandFields CLI
importCmd = command "import" (info (helper <*> fmap CLISub import_p) (progDesc "Import CLI."))

renderImportFunction :: ImportFunction -> T.Text
renderImportFunction = T.drop 3 . T.pack . show

import_p :: Parser CLICmd
import_p = fmap CCMD_import $ ImportArgs
  <$> ( option (eitherReader function_p) ( long "function"
                    <> help ("The function to use, one between: " <> (T.unpack $ T.intercalate "," $ map renderImportFunction [minBound .. maxBound]))
                    ) )
  <*> ( option str ( long "user") )
  <*> ( option str ( long "name") )
  <*> settings_p
  -- <*> (fmap Limit ( option auto ( long "limit" <> metavar "INT" <> help "The limit for the query") ))
  <*> ( option str ( long "corpus-path" <> help "Path to corpus file") )

function_p :: String -> Either String ImportFunction
function_p = \case
  "corpus"       -> Right IF_corpus
  "corpusTsvHal" -> Right IF_corpusTsvHal
  "annuaire"     -> Right IF_annuaire
  xs             -> Left $ "Unrecognised function: " <> xs
