{-# LANGUAGE FlexibleContexts #-}
-- | This modules provides a way to convert document identifiers, such
--  as DOIs, ISBNs, arXiv IDs to bibliographic references.
--
--  Each type of identifiers will be converted via internet services
--  to a bibliographic record of type 'Text.CSL.Reference' , which in
--  turn can be rendered in various format using @citeproc-hs@ package
--  <hackage.haskell.org/package/citeproc-hs> .
--
--  Moreover, the server responses are cached in a local database,
--  making the server load as little as possible.

module Text.CSL.Input.Identifier
       (resolveEither, resolve, withDBFile, DB(..), db)
       where

import           Control.Monad.IO.Class
import           Control.Monad.State as State
import           Control.Monad.Trans.Either
import           Data.Default
import           Text.CSL.Reference (emptyReference, Reference)
import           Text.CSL.Input.Identifier.Internal

-- $setup
-- >>> import Control.Applicative((<$>), (<*>))
-- >>> import Data.Either.Utils(forceEither)
-- >>> import Text.CSL



-- | Resolve a document url to a 'Reference'. returns an empty reference when someting fails.
--   prefix the document ID with one of "arXiv:", "doi:", "bibcode:" or "isbn:" .
--
--
-- >>> do { ref <- resolveDef "arXiv:1204.4779" ; putStrLn $ title ref }
-- Paraiso: an automated tuning framework for explicit solvers of partial differential equations
-- >>> do { ref <- resolveDef "doi:10.1088/1749-4699/5/1/015003" ; print $ author ref }
-- [Takayuki Muranushi]
-- >>> do { ref <- resolveDef "bibcode:2012CS&D....5a5003M" ; putStrLn $ containerTitle ref }
-- Computational Science and Discovery
-- >>> do { ref <- resolveDef "isbn:9784274068850" ; putStrLn $ title ref }
-- Sugoi hasukeru tanoshiku manabō


resolve :: (MonadIO m, MonadState DB m) => String -> m Reference
resolve = liftM (either (const emptyReference) id) . runEitherT . resolveEither

-- | Resolve the document id using the default database.

resolveDef :: String -> IO Reference
resolveDef url = do
  fn <- getDataFileName "default.db"
  let go = withDBFile fn $ resolve url
  State.evalStateT go def