{-# LANGUAGE TemplateHaskell #-}
{-|
Module:             IO
Description:        General IO functions specialized for 'Printable' instances.
Copyright:          © 2016 All rights reserved.
License:            GPL-3
Maintainer:         Evan Cofsky <evan@theunixman.com>
Stability:          experimental
Portability:        POSIX
-}

module IO (
    putStr,
    putStrLn,
    managed,
    Managed,
    MonadManaged(..),
    runManaged,
    TempFile,
    tfPath,
    tfHandle,
    tempFile,
    MonadIO,
    liftIO,
    PIO.hSeek,
    PIO.SeekMode(..),
    file
    ) where

import Lawless
import Control.Monad.IO.Class
import qualified System.Path.Directory as D
import qualified System.Path.IO as PIO
import qualified Data.Text.IO as T
import Text
import Textual
import Path
import Control.Monad.Managed.Safe
import Exception

liftPrintble  (MonadIO m, Printable p)  (Text  IO ())  p  m ()
liftPrintble f p = liftIO $ f (buildText  print $ p)

putStr  (MonadIO m, Printable p)  p  m ()
putStr = liftPrintble T.putStr

putStrLn  (MonadIO m, Printable p)  p  m ()
putStrLn = liftPrintble T.putStrLn

data TempFile = TempFile {
    _tfPath  AbsFile,
    _tfHandle  PIO.Handle
    }
makeLenses ''TempFile

tempFile  AbsDir  RelFile  Managed TempFile
tempFile pth tmpl =
    let
        open = do
            (p, h)  liftIO $ PIO.openTempFile pth tmpl
            liftIO $ PIO.hSetBuffering h PIO.NoBuffering
            liftIO $ PIO.hSetBinaryMode h True
            return $ TempFile p h

        close tf = do
            liftIO $ PIO.hClose $ tf ^. tfHandle
            liftIO $ D.removeFile $ tf ^. tfPath
    in
        managed $ bracket open close

file  AbsRelFile  PIO.IOMode  Managed PIO.Handle
file pth m = managed $ \fh  do
    liftIO $ PIO.withBinaryFile pth m fh