module Network.Neks.Disk (saveTo, loadFrom) where

import Control.Concurrent.STM (atomically)
import Network.Neks.DataStore (DataStore, dump, load)
import Network.Neks.NetPack (netRead, netWrite) -- also works on files
import System.IO (Handle, withFile, IOMode(ReadMode, WriteMode))
import System.Directory (renameFile, doesFileExist)
import Data.Serialize (Serialize, encode, decode)
import Control.Applicative ((<$>))

saveTo :: (Serialize a, Ord a, Serialize b) => String -> DataStore a b -> IO ()
saveTo path store = do
        withFile (path ++ "~") WriteMode (`saveToHandle` store)
        renameFile (path ++ "~") path
saveToHandle handle store = do
        maps <- atomically (dump store)
        sequence_ [netWrite handle (encode map) | map <- maps]

loadFrom :: (Serialize a, Ord a, Serialize b) => String -> IO (Maybe (DataStore a b))
loadFrom path = doesFileExist path >>= \exists -> if exists
        then Just <$> withFile path ReadMode loadFromHandle
        else return Nothing
loadFromHandle handle = do
        maps <- sequence . replicate 4096 $ do
                mapData <- netRead handle
                let Right map = mapData >>= decode
                return map
        atomically (load maps)