{-# LANGUAGE BangPatterns #-}
-- | Module: Text.Pandoc.PlantUML.Filter.Render
-- Defines the actual rendering done with PlantUML
module Text.Pandoc.PlantUML.Filter.IORender() where

import System.IO (hClose, hPutStr, IOMode(..), withBinaryFile, Handle)
import Data.ByteString.Lazy (hGetContents, hPut)
import System.Process
import System.Directory
import qualified Data.Text.IO as T
import qualified Data.Text    as T

import Text.Pandoc.PlantUML.Filter.Types

instance ImageIO IO where
  renderImage :: ImageFileName -> DiagramSource -> IO ()
renderImage ImageFileName
imageFileName (DiagramSource Text
source) = do
    (Just Handle
hIn, Just Handle
hOut, Maybe Handle
_, ProcessHandle
_) <- CreateProcess
-> IO (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)
createProcess (CreateProcess
 -> IO (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle))
-> CreateProcess
-> IO (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)
forall a b. (a -> b) -> a -> b
$ ImageFileName -> CreateProcess
plantUmlProcess ImageFileName
imageFileName
    Handle -> Text -> IO ()
T.hPutStr Handle
hIn Text
source
    Handle -> IO ()
hClose Handle
hIn
    (Handle -> IO ()) -> IO ()
forall r. (Handle -> IO r) -> IO r
withImageFile ((Handle -> IO ()) -> IO ()) -> (Handle -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ Handle -> Handle -> IO ()
pipe Handle
hOut
    Handle -> IO ()
hClose Handle
hOut
      where withImageFile :: (Handle -> IO r) -> IO r
withImageFile = FilePath -> IOMode -> (Handle -> IO r) -> IO r
forall r. FilePath -> IOMode -> (Handle -> IO r) -> IO r
withBinaryFile (ImageFileName -> FilePath
forall a. Show a => a -> FilePath
show ImageFileName
imageFileName) IOMode
WriteMode
  doesImageExist :: ImageFileName -> IO Bool
doesImageExist ImageFileName
imageFileName = FilePath -> IO Bool
doesFileExist (FilePath -> IO Bool) -> FilePath -> IO Bool
forall a b. (a -> b) -> a -> b
$ ImageFileName -> FilePath
forall a. Show a => a -> FilePath
show ImageFileName
imageFileName

plantUmlProcess :: ImageFileName -> CreateProcess
plantUmlProcess :: ImageFileName -> CreateProcess
plantUmlProcess (ImageFileName FilePath
_ Text
fileType) = (FilePath -> [FilePath] -> CreateProcess
proc FilePath
"java" [FilePath
"-jar", FilePath
"plantuml.jar", FilePath
"-pipe", FilePath
"-t" FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> Text -> FilePath
T.unpack Text
fileType])
  { std_in :: StdStream
std_in = StdStream
CreatePipe, std_out :: StdStream
std_out = StdStream
CreatePipe }

pipe :: Handle -> Handle -> IO ()
pipe :: Handle -> Handle -> IO ()
pipe Handle
hIn Handle
hOut = do
  !ByteString
input <- Handle -> IO ByteString
hGetContents Handle
hIn
  Handle -> ByteString -> IO ()
hPut Handle
hOut ByteString
input