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

Adaptative Phylo binaries
 -}

{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeOperators      #-}
{-# LANGUAGE Strict             #-}

module CLI.Phylo where

import CLI.Phylo.Common
import CLI.Types
import Data.Aeson (eitherDecodeFileStrict')
import Data.List  (nub)
import Data.Text qualified as T
import GHC.IO.Encoding
import Gargantext.Core.Viz.Phylo
import Gargantext.Core.Viz.Phylo.API.Tools
import Gargantext.Core.Viz.Phylo.PhyloExport (toPhyloExport, dotToFile)
import Gargantext.Core.Viz.Phylo.PhyloMaker  (toPhylo, toPhyloWithoutLink)
import Gargantext.Core.Viz.Phylo.PhyloTools  (printIOMsg, printIOComment, setConfig)
import Gargantext.Prelude hiding (hash, replace)
import Options.Applicative
import System.Directory (doesFileExist)

phyloCLI :: PhyloArgs -> IO ()
phyloCLI (PhyloArgs configPath) = do
  setLocaleEncoding utf8
  config_e <- eitherDecodeFileStrict' configPath
  case config_e of
    Left err -> panicTrace $ T.pack err
    Right config -> do
      currentLocale <- getLocaleEncoding
      printIOMsg $ "Machine locale: " <> show currentLocale
      printIOMsg "Starting the reconstruction"
      printIOMsg "Parse the corpus"
      mapList <-  fileToList (listParser config) (listPath config)

      corpus  <- if (defaultMode config)
                  then fileToDocsDefault (corpusParser config) (corpusPath config) [Year 3 1 5,Month 3 1 5,Week 4 2 5] mapList
                  else fileToDocsAdvanced (corpusParser config) (corpusPath config) (timeUnit config)  mapList

      printIOComment (show (length corpus) <> " parsed docs from the corpus")

      printIOComment (show (length $ nub $ concat $ map text corpus) <> " Size ngs_coterms")

      printIOComment (show (length mapList) <> " Size ngs_terms List Map Ngrams")

      printIOMsg "Reconstruct the phylo"

      -- check the existing backup files

      let backupPhyloWithoutLink = (outputPath config) <> "backupPhyloWithoutLink_" <> (configToSha BackupPhyloWithoutLink config) <> ".json"
      let backupPhylo = (outputPath config) <> "backupPhylo_"   <> (configToSha BackupPhylo config) <> ".json"

      phyloWithoutLinkExists <- doesFileExist backupPhyloWithoutLink
      phyloExists   <- doesFileExist backupPhylo

      -- reconstruct the phylo

      phylo <- if phyloExists
                  then do
                    printIOMsg "Reconstruct the phylo from an existing file"
                    readPhylo backupPhylo
                  else do
                    if phyloWithoutLinkExists
                      then do
                        printIOMsg "Reconstruct the phylo from an existing file without links"
                        phyloWithoutLink <- readPhylo backupPhyloWithoutLink
                        writePhylo backupPhyloWithoutLink phyloWithoutLink
                        pure $ toPhylo (setConfig config phyloWithoutLink)
                      else do
                        printIOMsg "Reconstruct the phylo from scratch"
                        phyloWithoutLink <- pure $ toPhyloWithoutLink corpus config
                        writePhylo backupPhyloWithoutLink phyloWithoutLink
                        pure $ toPhylo (setConfig config phyloWithoutLink)

      writePhylo backupPhylo phylo

      printIOMsg "End of reconstruction, start the export"

      let dot = toPhyloExport (setConfig config phylo)

      let output = configToLabel config

      dotToFile output dot

phyloCmd :: HasCallStack => Mod CommandFields CLI
phyloCmd = command "phylo" (info (helper <*> fmap CLISub phylo_p) (progDesc "Phylo toolkit."))

phylo_p :: Parser CLICmd
phylo_p = fmap CCMD_phylo $ PhyloArgs
  <$> ( strOption ( long "config"
                    <> metavar "FILEPATH"
                    <> help "Path to a file containing a JSON to be parsed into a PhyloConfig"
                    ) )
