{-|
Module      : Pipes.KeyValueCsv.IO
Copyright   : (c) Marcin Mrotek, 2015
License     : BSD3
Maintainer  : marcin.jan.mrotek@gmail.com
Stability   : experimental

File input and output.
-}

{-# LANGUAGE 
    DataKinds
  , FlexibleContexts 
  , PolyKinds
  , RankNTypes
  , TypeOperators
  #-}

module Pipes.KeyValueCsv.IO 
  ( streamIn
  , streamInBS
  -- * Re-exports
  , SafeT
  ) where 

import Prelude hiding (lines)

import Pipes.KeyValueCsv

import Data.Vinyl
import Data.Vinyl.Functor
import Pipes
import Pipes.ByteString (ByteString)
import qualified Pipes.ByteString as Pipes
import Pipes.Safe (SafeT, MonadMask)
import qualified Pipes.Safe as Pipes
import Pipes.Text.Encoding
import System.IO

streamInBS
  :: ( MonadIO m
     , MonadMask m
     )
  => FilePath
  -> Producer ByteString (SafeT m) ()
-- ^Read a 'ByteString' stream from file.
streamInBS path = 
    Pipes.bracket 
  ( liftIO $ openFile path ReadMode )
  ( liftIO . hClose )
    Pipes.fromHandle

streamIn 
  :: forall (m :: * -> *) (f :: k -> *) (g :: j -> *) (hs :: [k]) (rs :: [j])
   . ( MonadIO m
     , MonadMask m
     , Record hs
     )
  => Codec                       -- ^File encoding.
  -> FilePath                    -- ^Input file.
  -> Options (SafeT m) f g hs rs -- ^Parsing options.
  -> SafeT m
     ( Rec (WithKeyValueError :. f) hs
     , Producer (Rec (WithCsvError :. g) rs) (SafeT m)
       ( Producer ByteString (SafeT m) () )
    )
-- ^Read a CSV file.
streamIn codec path options = 
    parseKeyValueCsv options 
  . decode codec
  $ streamInBS path