module Bio.FASTA.Writer
  ( fastaToText
  , WritableFastaToken (..)
  ) where

import Bio.FASTA.Type  (Fasta, FastaItem (..), ModItem (..), modificationToString)
import Bio.Sequence    (BareSequence, sequ)
import Control.Lens    ((^.))
import Data.List.Split (chunksOf)
import Data.Text       (Text, pack)
import Data.Vector     (Vector, toList)
import Prelude         hiding (drop)

class WritableFastaToken a where
    tokenToString :: a -> String

instance WritableFastaToken Char where
    tokenToString :: Char -> String
tokenToString = forall (f :: * -> *) a. Applicative f => a -> f a
pure

instance WritableFastaToken ModItem where
    tokenToString :: ModItem -> String
tokenToString (Letter Char
l) = [Char
l]
    tokenToString (Mod Modification
m)    = Modification -> String
modificationToString Modification
m

fastaToText :: WritableFastaToken a => Fasta a -> Text
fastaToText :: forall a. WritableFastaToken a => Fasta a -> Text
fastaToText Fasta a
f = forall a. Monoid a => [a] -> a
mconcat forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map forall a. WritableFastaToken a => FastaItem a -> Text
writeItem Fasta a
f

writeItem :: WritableFastaToken a => FastaItem a -> Text
writeItem :: forall a. WritableFastaToken a => FastaItem a -> Text
writeItem (FastaItem Text
name BareSequence a
s) = Text
">" forall a. Semigroup a => a -> a -> a
<> Text
name forall a. Semigroup a => a -> a -> a
<> Text
"\n" forall a. Semigroup a => a -> a -> a
<> forall a. WritableFastaToken a => BareSequence a -> Text
seq2Text BareSequence a
s

seq2Text :: WritableFastaToken a => BareSequence a -> Text
seq2Text :: forall a. WritableFastaToken a => BareSequence a -> Text
seq2Text BareSequence a
s = String -> Text
pack forall a b. (a -> b) -> a -> b
$ forall a. WritableFastaToken a => Vector a -> String
vector2Text forall a b. (a -> b) -> a -> b
$ BareSequence a
s forall s a. s -> Getting a s a -> a
^. forall mk w a. Getter (Sequence mk w a) (Vector a)
Bio.Sequence.sequ

vector2Text :: WritableFastaToken a => Vector a -> String
vector2Text :: forall a. WritableFastaToken a => Vector a -> String
vector2Text Vector a
v = forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (forall a. [a] -> [a] -> [a]
++ String
"\n") forall a b. (a -> b) -> a -> b
$ forall e. Int -> [e] -> [[e]]
chunksOf Int
80 forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap forall a. WritableFastaToken a => a -> String
tokenToString forall a b. (a -> b) -> a -> b
$ forall a. Vector a -> [a]
toList Vector a
v