{-# LANGUAGE DeriveGeneric #-}

-- |
-- Module      :  SLynx.Translate.Options
-- Description :  ELynxSeq argument parsing
-- Copyright   :  (c) Dominik Schrempf 2021
-- License     :  GPL-3.0-or-later
--
-- Maintainer  :  dominik.schrempf@gmail.com
-- Stability   :  unstable
-- Portability :  portable
--
-- Creation date: Sun Oct  7 17:29:45 2018.
module SLynx.Translate.Options
  ( TranslateArguments (..),
    translateArguments,
  )
where

import Data.List
import ELynx.Data.Alphabet.Alphabet
import ELynx.Data.Character.Codon
import ELynx.Tools
import Options.Applicative
import SLynx.Tools

-- | Arguments needed to translate sequences.
data TranslateArguments = TranslateArguments
  { TranslateArguments -> Alphabet
trAlphabet :: Alphabet,
    TranslateArguments -> FilePath
trInFile :: FilePath,
    TranslateArguments -> Int
trReadingFrame :: Int,
    TranslateArguments -> UniversalCode
trUniversalCode :: UniversalCode
  }
  deriving (TranslateArguments -> TranslateArguments -> Bool
(TranslateArguments -> TranslateArguments -> Bool)
-> (TranslateArguments -> TranslateArguments -> Bool)
-> Eq TranslateArguments
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TranslateArguments -> TranslateArguments -> Bool
$c/= :: TranslateArguments -> TranslateArguments -> Bool
== :: TranslateArguments -> TranslateArguments -> Bool
$c== :: TranslateArguments -> TranslateArguments -> Bool
Eq, Int -> TranslateArguments -> ShowS
[TranslateArguments] -> ShowS
TranslateArguments -> FilePath
(Int -> TranslateArguments -> ShowS)
-> (TranslateArguments -> FilePath)
-> ([TranslateArguments] -> ShowS)
-> Show TranslateArguments
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
showList :: [TranslateArguments] -> ShowS
$cshowList :: [TranslateArguments] -> ShowS
show :: TranslateArguments -> FilePath
$cshow :: TranslateArguments -> FilePath
showsPrec :: Int -> TranslateArguments -> ShowS
$cshowsPrec :: Int -> TranslateArguments -> ShowS
Show, (forall x. TranslateArguments -> Rep TranslateArguments x)
-> (forall x. Rep TranslateArguments x -> TranslateArguments)
-> Generic TranslateArguments
forall x. Rep TranslateArguments x -> TranslateArguments
forall x. TranslateArguments -> Rep TranslateArguments x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep TranslateArguments x -> TranslateArguments
$cfrom :: forall x. TranslateArguments -> Rep TranslateArguments x
Generic)

instance Reproducible TranslateArguments where
  inFiles :: TranslateArguments -> [FilePath]
inFiles = FilePath -> [FilePath]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (FilePath -> [FilePath])
-> (TranslateArguments -> FilePath)
-> TranslateArguments
-> [FilePath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TranslateArguments -> FilePath
trInFile
  outSuffixes :: TranslateArguments -> [FilePath]
outSuffixes TranslateArguments
_ = [FilePath
".fasta"]
  getSeed :: TranslateArguments -> Maybe SeedOpt
getSeed TranslateArguments
_ = Maybe SeedOpt
forall a. Maybe a
Nothing
  setSeed :: TranslateArguments -> SeedOpt -> TranslateArguments
setSeed = TranslateArguments -> SeedOpt -> TranslateArguments
forall a b. a -> b -> a
const
  parser :: Parser TranslateArguments
parser = Parser TranslateArguments
translateArguments
  cmdName :: FilePath
cmdName = FilePath
"translate"
  cmdDsc :: [FilePath]
cmdDsc = [FilePath
"Translate from DNA to Protein or DNAX to ProteinX."]

instance FromJSON TranslateArguments

instance ToJSON TranslateArguments

-- | Command line parser.
translateArguments :: Parser TranslateArguments
translateArguments :: Parser TranslateArguments
translateArguments =
  Alphabet -> FilePath -> Int -> UniversalCode -> TranslateArguments
TranslateArguments
    (Alphabet
 -> FilePath -> Int -> UniversalCode -> TranslateArguments)
-> Parser Alphabet
-> Parser (FilePath -> Int -> UniversalCode -> TranslateArguments)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Alphabet
alphabetOpt
    Parser (FilePath -> Int -> UniversalCode -> TranslateArguments)
-> Parser FilePath
-> Parser (Int -> UniversalCode -> TranslateArguments)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser FilePath
inFileArg
    Parser (Int -> UniversalCode -> TranslateArguments)
-> Parser Int -> Parser (UniversalCode -> TranslateArguments)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Int
readingFrameOpt
    Parser (UniversalCode -> TranslateArguments)
-> Parser UniversalCode -> Parser TranslateArguments
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser UniversalCode
universalCodeOpt

readingFrameOpt :: Parser Int
readingFrameOpt :: Parser Int
readingFrameOpt =
  ReadM Int -> Mod OptionFields Int -> Parser Int
forall a. ReadM a -> Mod OptionFields a -> Parser a
option ReadM Int
forall a. Read a => ReadM a
auto (Mod OptionFields Int -> Parser Int)
-> Mod OptionFields Int -> Parser Int
forall a b. (a -> b) -> a -> b
$
    FilePath -> Mod OptionFields Int
forall (f :: * -> *) a. HasName f => FilePath -> Mod f a
long FilePath
"reading-frame" Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Semigroup a => a -> a -> a
<> Char -> Mod OptionFields Int
forall (f :: * -> *) a. HasName f => Char -> Mod f a
short Char
'r' Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields Int
forall (f :: * -> *) a. HasMetavar f => FilePath -> Mod f a
metavar FilePath
"INT"
      Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields Int
forall (f :: * -> *) a. FilePath -> Mod f a
help
        FilePath
"Reading frame [0|1|2]."

universalCodeOpt :: Parser UniversalCode
universalCodeOpt :: Parser UniversalCode
universalCodeOpt =
  ReadM UniversalCode
-> Mod OptionFields UniversalCode -> Parser UniversalCode
forall a. ReadM a -> Mod OptionFields a -> Parser a
option ReadM UniversalCode
forall a. Read a => ReadM a
auto (Mod OptionFields UniversalCode -> Parser UniversalCode)
-> Mod OptionFields UniversalCode -> Parser UniversalCode
forall a b. (a -> b) -> a -> b
$
    FilePath -> Mod OptionFields UniversalCode
forall (f :: * -> *) a. HasName f => FilePath -> Mod f a
long FilePath
"universal-code" Mod OptionFields UniversalCode
-> Mod OptionFields UniversalCode -> Mod OptionFields UniversalCode
forall a. Semigroup a => a -> a -> a
<> Char -> Mod OptionFields UniversalCode
forall (f :: * -> *) a. HasName f => Char -> Mod f a
short Char
'u' Mod OptionFields UniversalCode
-> Mod OptionFields UniversalCode -> Mod OptionFields UniversalCode
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields UniversalCode
forall (f :: * -> *) a. HasMetavar f => FilePath -> Mod f a
metavar FilePath
"CODE"
      Mod OptionFields UniversalCode
-> Mod OptionFields UniversalCode -> Mod OptionFields UniversalCode
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod OptionFields UniversalCode
forall (f :: * -> *) a. FilePath -> Mod f a
help
        (FilePath
"universal code; one of: " FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ FilePath
codeStr FilePath -> ShowS
forall a. [a] -> [a] -> [a]
++ FilePath
".")
  where
    codes :: [UniversalCode]
codes = [UniversalCode]
forall a. (Bounded a, Enum a) => [a]
allValues :: [UniversalCode]
    codeWords :: [FilePath]
codeWords = (UniversalCode -> FilePath) -> [UniversalCode] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map UniversalCode -> FilePath
forall a. Show a => a -> FilePath
show [UniversalCode]
codes
    codeStr :: FilePath
codeStr = FilePath -> [FilePath] -> FilePath
forall a. [a] -> [[a]] -> [a]
intercalate FilePath
", " [FilePath]
codeWords

inFileArg :: Parser FilePath
inFileArg :: Parser FilePath
inFileArg =
  Mod ArgumentFields FilePath -> Parser FilePath
forall s. IsString s => Mod ArgumentFields s -> Parser s
strArgument (Mod ArgumentFields FilePath -> Parser FilePath)
-> Mod ArgumentFields FilePath -> Parser FilePath
forall a b. (a -> b) -> a -> b
$ FilePath -> Mod ArgumentFields FilePath
forall (f :: * -> *) a. HasMetavar f => FilePath -> Mod f a
metavar FilePath
"INPUT-FILE" Mod ArgumentFields FilePath
-> Mod ArgumentFields FilePath -> Mod ArgumentFields FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath -> Mod ArgumentFields FilePath
forall (f :: * -> *) a. FilePath -> Mod f a
help FilePath
"Read sequences from INPUT-FILE"