{-# LANGUAGE OverloadedStrings #-}

module Poseidon.CLI.Init where

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

import           Control.Monad          (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
gd [Char]
outPathRaw Maybe [Char]
maybeOutName Bool
minimal) = do
    let (GenotypeDataSpec GenotypeFormatSpec
format_ [Char]
genoFile_ Maybe [Char]
_ [Char]
snpFile_ Maybe [Char]
_ [Char]
indFile_ Maybe [Char]
_ Maybe SNPSetSpec
snpSet_) = GenotypeDataSpec
gd
    -- 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
    let outInd :: [Char]
outInd = [Char] -> [Char]
takeFileName [Char]
indFile_
        outSnp :: [Char]
outSnp = [Char] -> [Char]
takeFileName [Char]
snpFile_
        outGeno :: [Char]
outGeno = [Char] -> [Char]
takeFileName [Char]
genoFile_
        genotypeData :: GenotypeDataSpec
genotypeData = GenotypeFormatSpec
-> [Char]
-> Maybe [Char]
-> [Char]
-> Maybe [Char]
-> [Char]
-> Maybe [Char]
-> Maybe SNPSetSpec
-> GenotypeDataSpec
GenotypeDataSpec GenotypeFormatSpec
format_ [Char]
outGeno Maybe [Char]
forall a. Maybe a
Nothing [Char]
outSnp Maybe [Char]
forall a. Maybe a
Nothing [Char]
outInd Maybe [Char]
forall a. Maybe a
Nothing Maybe SNPSetSpec
snpSet_
    -- genotype data
    [Char] -> PoseidonIO ()
logInfo [Char]
"Copying genotype data"
    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]
indFile_ Maybe [Char]
forall a. Maybe a
Nothing
    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]
snpFile_ Maybe [Char]
forall a. Maybe a
Nothing
    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]
genoFile_ Maybe [Char]
forall a. Maybe a
Nothing
    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]
indFile_ ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
outPath [Char] -> [Char] -> [Char]
</> [Char]
outInd
    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]
snpFile_ ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
outPath [Char] -> [Char] -> [Char]
</> [Char]
outSnp
    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]
genoFile_ ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
outPath [Char] -> [Char] -> [Char]
</> [Char]
outGeno
    -- 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
genotypeData
    PoseidonPackage
pac <- if Bool
minimal
           then PoseidonPackage -> ReaderT Env IO PoseidonPackage
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (PoseidonPackage -> ReaderT Env IO PoseidonPackage)
-> PoseidonPackage -> ReaderT Env IO PoseidonPackage
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char] -> GenotypeDataSpec -> PoseidonPackage
newMinimalPackageTemplate [Char]
outPath [Char]
outName GenotypeDataSpec
genotypeData
           else [Char]
-> [Char]
-> GenotypeDataSpec
-> Maybe (Either [EigenstratIndEntry] JannoRows)
-> SeqSourceRows
-> BibTeX
-> ReaderT Env IO PoseidonPackage
newPackageTemplate [Char]
outPath [Char]
outName GenotypeDataSpec
genotypeData (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