{-# LANGUAGE CPP #-}

module Bio.FASTA
  ( module T
  , WritableFastaToken (..)
  , fromFile
  , toFile
  , fastaP
  , fastaLine
  , modificationP
  , Parser
  ) where

import Control.Monad.IO.Class (MonadIO, liftIO)
import Data.Text.IO           (readFile, writeFile)
import System.FilePath        (takeBaseName)
import Text.Megaparsec        (errorBundlePretty, parse)
#if !MIN_VERSION_base(4,13,0)
import Control.Monad.Fail (MonadFail (..))
import Prelude            hiding (fail, readFile, writeFile)
#else
import Prelude hiding (readFile, writeFile)
#endif

import Bio.FASTA.Parser
import Bio.FASTA.Type   as T
import Bio.FASTA.Writer (WritableFastaToken (..), fastaToText)

-- | Reads 'FastaSequence' from given file.
--
fromFile :: (MonadFail m, MonadIO m, ParsableFastaToken a) => FilePath -> m (Fasta a)
fromFile :: forall (m :: * -> *) a.
(MonadFail m, MonadIO m, ParsableFastaToken a) =>
FilePath -> m (Fasta a)
fromFile FilePath
f = IO Text -> m Text
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (FilePath -> IO Text
readFile FilePath
f) m Text -> (Text -> m (Fasta a)) -> m (Fasta a)
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (ParseErrorBundle Text Void -> m (Fasta a))
-> (Fasta a -> m (Fasta a))
-> Either (ParseErrorBundle Text Void) (Fasta a)
-> m (Fasta a)
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (FilePath -> m (Fasta a)
forall a. FilePath -> m a
forall (m :: * -> *) a. MonadFail m => FilePath -> m a
fail (FilePath -> m (Fasta a))
-> (ParseErrorBundle Text Void -> FilePath)
-> ParseErrorBundle Text Void
-> m (Fasta a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ParseErrorBundle Text Void -> FilePath
forall s e.
(VisualStream s, TraversableStream s, ShowErrorComponent e) =>
ParseErrorBundle s e -> FilePath
errorBundlePretty) Fasta a -> m (Fasta a)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either (ParseErrorBundle Text Void) (Fasta a) -> m (Fasta a))
-> (Text -> Either (ParseErrorBundle Text Void) (Fasta a))
-> Text
-> m (Fasta a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Parsec Void Text (Fasta a)
-> FilePath
-> Text
-> Either (ParseErrorBundle Text Void) (Fasta a)
forall e s a.
Parsec e s a -> FilePath -> s -> Either (ParseErrorBundle s e) a
parse Parsec Void Text (Fasta a)
forall a. ParsableFastaToken a => Parser (Fasta a)
fastaP (FilePath -> FilePath
takeBaseName FilePath
f)

-- | Writes 'FastaSequence' to file.
--
toFile :: MonadIO m => Fasta Char -> FilePath -> m ()
toFile :: forall (m :: * -> *). MonadIO m => Fasta Char -> FilePath -> m ()
toFile Fasta Char
s FilePath
f = IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath -> Text -> IO ()
writeFile FilePath
f (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ Fasta Char -> Text
forall a. WritableFastaToken a => Fasta a -> Text
fastaToText Fasta Char
s