{-# LANGUAGE OverloadedStrings #-}

module Poseidon.CLI.Init where

import           Poseidon.BibFile       (dummyBibEntry, writeBibTeXFile)
import           Poseidon.GenotypeData  (GenotypeDataSpec (..),
                                         GenotypeFileSpec (..), loadIndividuals,
                                         reduceGenotypeFilepaths)
import           Poseidon.Janno         (writeJannoFile)
import           Poseidon.Package       (PoseidonPackage (..),
                                         newMinimalPackageTemplate,
                                         newPackageTemplate,
                                         writePoseidonPackage)
import           Poseidon.Utils         (PoseidonIO, checkFile,
                                         determinePackageOutName, logInfo)

import           Control.Monad          (forM_, unless)
import           Control.Monad.IO.Class (liftIO)
import           System.Directory       (copyFile, createDirectoryIfMissing)
import           System.FilePath        (dropTrailingPathSeparator,
                                         takeFileName, (<.>), (</>))

data InitOptions = InitOptions
    { InitOptions -> GenotypeDataSpec
_initGenoData :: GenotypeDataSpec
    , InitOptions -> [Char]
_initPacPath  :: FilePath
    , InitOptions -> Maybe [Char]
_initPacName  :: Maybe String
    , InitOptions -> Bool
_initMinimal  :: Bool
    }

runInit :: InitOptions -> PoseidonIO ()
runInit :: InitOptions -> PoseidonIO ()
runInit (InitOptions GenotypeDataSpec
genotypeDataIn [Char]
outPathRaw Maybe [Char]
maybeOutName Bool
minimal) = do
    -- create new directory
    let outPath :: [Char]
outPath = [Char] -> [Char]
dropTrailingPathSeparator [Char]
outPathRaw
    [Char] -> PoseidonIO ()
logInfo ([Char] -> PoseidonIO ()) -> [Char] -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ [Char]
"Creating new package directory: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
outPath
    IO () -> PoseidonIO ()
forall a. IO a -> ReaderT Env IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> PoseidonIO ()) -> IO () -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ Bool -> [Char] -> IO ()
createDirectoryIfMissing Bool
True [Char]
outPath
    -- compile genotype data structure
    GenotypeDataSpec
genotypeDataOut <- ([Char], GenotypeDataSpec) -> GenotypeDataSpec
forall a b. (a, b) -> b
snd (([Char], GenotypeDataSpec) -> GenotypeDataSpec)
-> ReaderT Env IO ([Char], GenotypeDataSpec)
-> ReaderT Env IO GenotypeDataSpec
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GenotypeDataSpec -> ReaderT Env IO ([Char], GenotypeDataSpec)
forall (m :: * -> *).
MonadThrow m =>
GenotypeDataSpec -> m ([Char], GenotypeDataSpec)
reduceGenotypeFilepaths GenotypeDataSpec
genotypeDataIn
    -- genotype data
    [Char] -> PoseidonIO ()
logInfo [Char]
"Copying genotype data"
    let sourceFiles :: [[Char]]
sourceFiles = case GenotypeDataSpec -> GenotypeFileSpec
genotypeFileSpec GenotypeDataSpec
genotypeDataIn of
            GenotypeEigenstrat [Char]
genoFile Maybe [Char]
_ [Char]
snpFile Maybe [Char]
_ [Char]
indFile Maybe [Char]
_ -> [[Char]
genoFile, [Char]
snpFile, [Char]
indFile]
            GenotypePlink      [Char]
genoFile Maybe [Char]
_ [Char]
snpFile Maybe [Char]
_ [Char]
indFile Maybe [Char]
_ -> [[Char]
genoFile, [Char]
snpFile, [Char]
indFile]
            GenotypeVCF        [Char]
vcfFile  Maybe [Char]
_                     -> [[Char]
vcfFile]
    [[Char]] -> ([Char] -> PoseidonIO ()) -> PoseidonIO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [[Char]]
sourceFiles (([Char] -> PoseidonIO ()) -> PoseidonIO ())
-> ([Char] -> PoseidonIO ()) -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ \[Char]
sourceFile -> do
        IO () -> PoseidonIO ()
forall a. IO a -> ReaderT Env IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> PoseidonIO ()) -> IO () -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ [Char] -> Maybe [Char] -> IO ()
checkFile [Char]
sourceFile Maybe [Char]
forall a. Maybe a
Nothing
        let targetFile :: [Char]
targetFile = [Char]
outPath [Char] -> [Char] -> [Char]
</> [Char] -> [Char]
takeFileName [Char]
sourceFile
        IO () -> PoseidonIO ()
forall a. IO a -> ReaderT Env IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> PoseidonIO ()) -> IO () -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char] -> IO ()
copyFile [Char]
sourceFile [Char]
targetFile
    -- create new package
    [Char] -> PoseidonIO ()
logInfo [Char]
"Creating new package entity"
    [Char]
outName <- IO [Char] -> ReaderT Env IO [Char]
forall a. IO a -> ReaderT Env IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO [Char] -> ReaderT Env IO [Char])
-> IO [Char] -> ReaderT Env IO [Char]
forall a b. (a -> b) -> a -> b
$ Maybe [Char] -> [Char] -> IO [Char]
determinePackageOutName Maybe [Char]
maybeOutName [Char]
outPath
    [EigenstratIndEntry]
inds <- [Char] -> GenotypeDataSpec -> PoseidonIO [EigenstratIndEntry]
loadIndividuals [Char]
outPath GenotypeDataSpec
genotypeDataOut
    PoseidonPackage
pac <- if Bool
minimal
           then [Char]
-> [Char] -> GenotypeDataSpec -> ReaderT Env IO PoseidonPackage
forall (m :: * -> *).
MonadThrow m =>
[Char] -> [Char] -> GenotypeDataSpec -> m PoseidonPackage
newMinimalPackageTemplate [Char]
outPath [Char]
outName GenotypeDataSpec
genotypeDataOut
           else [Char]
-> [Char]
-> GenotypeDataSpec
-> Maybe (Either [EigenstratIndEntry] JannoRows)
-> SeqSourceRows
-> BibTeX
-> ReaderT Env IO PoseidonPackage
newPackageTemplate [Char]
outPath [Char]
outName GenotypeDataSpec
genotypeDataOut (Either [EigenstratIndEntry] JannoRows
-> Maybe (Either [EigenstratIndEntry] JannoRows)
forall a. a -> Maybe a
Just ([EigenstratIndEntry] -> Either [EigenstratIndEntry] JannoRows
forall a b. a -> Either a b
Left [EigenstratIndEntry]
inds)) SeqSourceRows
forall a. Monoid a => a
mempty [BibEntry
dummyBibEntry]
    -- POSEIDON.yml
    [Char] -> PoseidonIO ()
logInfo [Char]
"Creating POSEIDON.yml"
    IO () -> PoseidonIO ()
forall a. IO a -> ReaderT Env IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> PoseidonIO ()) -> IO () -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ PoseidonPackage -> IO ()
writePoseidonPackage PoseidonPackage
pac
    Bool -> PoseidonIO () -> PoseidonIO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
minimal (PoseidonIO () -> PoseidonIO ()) -> PoseidonIO () -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ do
        -- janno
        [Char] -> PoseidonIO ()
logInfo [Char]
"Creating minimal .janno file"
        IO () -> PoseidonIO ()
forall a. IO a -> ReaderT Env IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> PoseidonIO ()) -> IO () -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ [Char] -> JannoRows -> IO ()
writeJannoFile ([Char]
outPath [Char] -> [Char] -> [Char]
</> [Char]
outName [Char] -> [Char] -> [Char]
<.> [Char]
"janno") (JannoRows -> IO ()) -> JannoRows -> IO ()
forall a b. (a -> b) -> a -> b
$ PoseidonPackage -> JannoRows
posPacJanno PoseidonPackage
pac
        -- bib
        [Char] -> PoseidonIO ()
logInfo [Char]
"Creating dummy .bib file"
        IO () -> PoseidonIO ()
forall a. IO a -> ReaderT Env IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> PoseidonIO ()) -> IO () -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ [Char] -> BibTeX -> IO ()
writeBibTeXFile ([Char]
outPath [Char] -> [Char] -> [Char]
</> [Char]
outName [Char] -> [Char] -> [Char]
<.> [Char]
"bib") (BibTeX -> IO ()) -> BibTeX -> IO ()
forall a b. (a -> b) -> a -> b
$ PoseidonPackage -> BibTeX
posPacBib PoseidonPackage
pac