{-# LANGUAGE CPP #-}

module Bio.Uniprot
  ( module T
  , parseRecord
  , fetch
  ) where

import           Data.Text.Encoding     ( decodeUtf8 )
import           Data.String            ( IsString(..) )
import           Data.Attoparsec.Text   ( parseOnly )
import           Control.Monad.IO.Class ( MonadIO )
import           Network.HTTP.Simple    ( httpBS, getResponseBody )
#if !MIN_VERSION_base(4,13,0)
import           Control.Monad.Fail     ( MonadFail(..) )
import           Prelude                hiding ( fail )
#endif

import           Bio.Uniprot.Type       as T
import           Bio.Uniprot.Parser

-- | Fetches Uniprot record from Uniprot
fetch :: (MonadFail m, MonadIO m) => String -> m Record
fetch :: String -> m Record
fetch String
recid = do let url :: Request
url = String -> Request
forall a. IsString a => String -> a
fromString (String -> Request) -> String -> Request
forall a b. (a -> b) -> a -> b
$ String
"https://www.uniprot.org/uniprot/" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
recid String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
".txt"
                 Response ByteString
resp <- Request -> m (Response ByteString)
forall (m :: * -> *).
MonadIO m =>
Request -> m (Response ByteString)
httpBS Request
url
                 case Parser Record -> Text -> Either String Record
forall a. Parser a -> Text -> Either String a
parseOnly Parser Record
parseRecord (ByteString -> Text
decodeUtf8 (ByteString -> Text) -> ByteString -> Text
forall a b. (a -> b) -> a -> b
$ Response ByteString -> ByteString
forall a. Response a -> a
getResponseBody Response ByteString
resp) of
                   Left String
err -> String -> m Record
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
err
                   Right Record
r  -> Record -> m Record
forall (f :: * -> *) a. Applicative f => a -> f a
pure Record
r