{-| Dictionary IO functions.

-}
module Shikensu.Contrib.IO
    ( Shikensu.Contrib.IO.read
    , Shikensu.Contrib.IO.readDef
    , Shikensu.Contrib.IO.write
    , Shikensu.Contrib.IO.writeDef
    ) where

import Data.Maybe (fromMaybe)
import Shikensu.Internal.Types
import System.Directory (createDirectoryIfMissing, doesFileExist)
import System.FilePath (FilePath, joinPath, takeDirectory)

import qualified Data.ByteString as B (empty, readFile, writeFile)
import qualified Shikensu.Utilities as Utilities (mapIO)


{-| Read.

Read the contents of each file, and for each file (ie. definition)
put that content in the `content` property.
-}
read :: Dictionary -> IO Dictionary
read :: Dictionary -> IO Dictionary
read =
    (Definition -> IO Definition) -> Dictionary -> IO Dictionary
Utilities.mapIO Definition -> IO Definition
readDef


readDef :: Definition -> IO Definition
readDef :: Definition -> IO Definition
readDef Definition
def =
    let
        absPath :: String
absPath = Definition -> String
absolutePath Definition
def
    in
        String -> IO Bool
doesFileExist String
absPath IO Bool -> (Bool -> IO Definition) -> IO Definition
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Bool
exists ->
            if Bool
exists then
                (ByteString -> Definition) -> IO ByteString -> IO Definition
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap
                    (\ByteString
c -> Definition
def { $sel:content:Definition :: Maybe ByteString
content = ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just ByteString
c })
                    (String -> IO ByteString
B.readFile String
absPath)
            else
                Definition -> IO Definition
forall (m :: * -> *) a. Monad m => a -> m a
return
                    Definition
def { $sel:content:Definition :: Maybe ByteString
content = Maybe ByteString
forall a. Maybe a
Nothing }



{-| Write.

Write the contents of each definition to a file.
The path of the new file is `joinPath [rootDirname, givenDirectoryName, localPath]`.
-}
write :: FilePath -> Dictionary -> IO Dictionary
write :: String -> Dictionary -> IO Dictionary
write String
dest =
    (Definition -> IO Definition) -> Dictionary -> IO Dictionary
Utilities.mapIO (String -> Definition -> IO Definition
writeDef String
dest)


writeDef :: FilePath -> Definition -> IO Definition
writeDef :: String -> Definition -> IO Definition
writeDef String
dest Definition
def =
    let
        path :: String
path = [String] -> String
joinPath [Definition -> String
rootDirname Definition
def, String
dest, Definition -> String
localPath Definition
def]
        cont :: ByteString
cont = ByteString -> Maybe ByteString -> ByteString
forall a. a -> Maybe a -> a
fromMaybe ByteString
B.empty (Definition -> Maybe ByteString
content Definition
def)
    in
        Bool -> String -> IO ()
createDirectoryIfMissing Bool
True (String -> String
takeDirectory String
path)
            IO () -> IO () -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> String -> ByteString -> IO ()
B.writeFile String
path ByteString
cont
            IO () -> IO Definition -> IO Definition
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Definition -> IO Definition
forall (m :: * -> *) a. Monad m => a -> m a
return Definition
def