module Drasil.Generator.ChunkDump (
  -- * Tools for dumping a chunk database to disk for debugging
  dumpEverything
) where

import Control.Lens ((^.))
import Data.Aeson (ToJSON)
import Data.Aeson.Encode.Pretty (encodePretty)
import qualified Data.ByteString.Lazy.Char8 as LB
import System.IO (IOMode(WriteMode), openFile, hClose)
import System.Environment (lookupEnv)

import Drasil.Build.Artifacts (createDirIfMissing)
import Drasil.Database (dumpChunkDB)
import Drasil.System (SmithEtAlSRS, systemdb, traceTable, refbyTable)

type Path = String
type TargetFile = String

-- | For debugging purposes, if the system has a `DEBUG_ENV` environment
-- variable set to anything, we can dump the chunk maps in a system to the host
-- system.
dumpEverything :: SmithEtAlSRS -> Path -> IO ()
dumpEverything :: SmithEtAlSRS -> [Char] -> IO ()
dumpEverything SmithEtAlSRS
si [Char]
p = do
  Maybe [Char]
maybeDebugging <- [Char] -> IO (Maybe [Char])
lookupEnv [Char]
"DEBUG_ENV"
  case Maybe [Char]
maybeDebugging of
    (Just (Char
_:[Char]
_)) -> do
      SmithEtAlSRS -> [Char] -> IO ()
dumpEverything0 SmithEtAlSRS
si [Char]
p
    Maybe [Char]
_ -> IO ()
forall a. Monoid a => a
mempty

dumpEverything0 :: SmithEtAlSRS -> Path -> IO ()
dumpEverything0 :: SmithEtAlSRS -> [Char] -> IO ()
dumpEverything0 SmithEtAlSRS
si [Char]
targetPath = do
  Bool -> [Char] -> IO ()
createDirIfMissing Bool
True [Char]
targetPath
  let chunkDb :: ChunkDB
chunkDb = SmithEtAlSRS
si SmithEtAlSRS -> Getting ChunkDB SmithEtAlSRS ChunkDB -> ChunkDB
forall s a. s -> Getting a s a -> a
^. Getting ChunkDB SmithEtAlSRS ChunkDB
forall c. HasSystemMeta c => Lens' c ChunkDB
Lens' SmithEtAlSRS ChunkDB
systemdb
      chunkDump :: DumpedChunkDB
chunkDump = ChunkDB -> DumpedChunkDB
dumpChunkDB ChunkDB
chunkDb
      traceDump :: Map UID [UID]
traceDump = SmithEtAlSRS
si SmithEtAlSRS
-> Getting (Map UID [UID]) SmithEtAlSRS (Map UID [UID])
-> Map UID [UID]
forall s a. s -> Getting a s a -> a
^. Getting (Map UID [UID]) SmithEtAlSRS (Map UID [UID])
forall c. HasSmithEtAlSRS c => Lens' c (Map UID [UID])
Lens' SmithEtAlSRS (Map UID [UID])
traceTable
      refByDump :: Map UID [UID]
refByDump = SmithEtAlSRS
si SmithEtAlSRS
-> Getting (Map UID [UID]) SmithEtAlSRS (Map UID [UID])
-> Map UID [UID]
forall s a. s -> Getting a s a -> a
^. Getting (Map UID [UID]) SmithEtAlSRS (Map UID [UID])
forall c. HasSmithEtAlSRS c => Lens' c (Map UID [UID])
Lens' SmithEtAlSRS (Map UID [UID])
refbyTable

  DumpedChunkDB -> [Char] -> IO ()
forall a. ToJSON a => a -> [Char] -> IO ()
dumpTo DumpedChunkDB
chunkDump ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
targetPath [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"seeds.json"
  Map UID [UID] -> [Char] -> IO ()
forall a. ToJSON a => a -> [Char] -> IO ()
dumpTo Map UID [UID]
traceDump ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
targetPath [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"trace.json"
  Map UID [UID] -> [Char] -> IO ()
forall a. ToJSON a => a -> [Char] -> IO ()
dumpTo Map UID [UID]
refByDump ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
targetPath [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"reverse_trace.json"

-- FIXME: This is more of a general utility than it is drasil-database specific
dumpTo :: ToJSON a => a -> TargetFile -> IO ()
dumpTo :: forall a. ToJSON a => a -> [Char] -> IO ()
dumpTo a
d [Char]
targetFile = do
  Handle
trg <- [Char] -> IOMode -> IO Handle
openFile [Char]
targetFile IOMode
WriteMode
  Handle -> ByteString -> IO ()
LB.hPutStrLn Handle
trg (ByteString -> IO ()) -> ByteString -> IO ()
forall a b. (a -> b) -> a -> b
$ a -> ByteString
forall a. ToJSON a => a -> ByteString
encodePretty a
d
  Handle -> IO ()
hClose Handle
trg