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, hPutStrLn)
import System.Environment (lookupEnv)
import Text.PrettyPrint (render)

import Language.Drasil.Printers (PrintingInformation, printAllDebugInfo)
import Utils.Drasil (createDirIfMissing)
import Drasil.Database (dumpChunkDB)
import Drasil.System (System, 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 :: System -> PrintingInformation -> Path -> IO ()
dumpEverything :: System -> PrintingInformation -> [Char] -> IO ()
dumpEverything System
si PrintingInformation
pinfo [Char]
p = do
  Maybe [Char]
maybeDebugging <- [Char] -> IO (Maybe [Char])
lookupEnv [Char]
"DEBUG_ENV"
  case Maybe [Char]
maybeDebugging of
    (Just (Char
_:[Char]
_)) -> do
      System -> PrintingInformation -> [Char] -> IO ()
dumpEverything0 System
si PrintingInformation
pinfo [Char]
p
    Maybe [Char]
_ -> IO ()
forall a. Monoid a => a
mempty

dumpEverything0 :: System -> PrintingInformation -> Path -> IO ()
dumpEverything0 :: System -> PrintingInformation -> [Char] -> IO ()
dumpEverything0 System
si PrintingInformation
pinfo [Char]
targetPath = do
  Bool -> [Char] -> IO ()
createDirIfMissing Bool
True [Char]
targetPath
  let chunkDb :: ChunkDB
chunkDb = System
si System -> Getting ChunkDB System ChunkDB -> ChunkDB
forall s a. s -> Getting a s a -> a
^. Getting ChunkDB System ChunkDB
forall c. HasSystem c => Lens' c ChunkDB
Lens' System ChunkDB
systemdb
      chunkDump :: DumpedChunkDB
chunkDump = ChunkDB -> DumpedChunkDB
dumpChunkDB ChunkDB
chunkDb
      traceDump :: UIDMap
traceDump = System
si System -> Getting UIDMap System UIDMap -> UIDMap
forall s a. s -> Getting a s a -> a
^. Getting UIDMap System UIDMap
forall c. HasSystem c => Lens' c UIDMap
Lens' System UIDMap
traceTable
      refByDump :: UIDMap
refByDump = System
si System -> Getting UIDMap System UIDMap -> UIDMap
forall s a. s -> Getting a s a -> a
^. Getting UIDMap System UIDMap
forall c. HasSystem c => Lens' c UIDMap
Lens' System UIDMap
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"
  UIDMap -> [Char] -> IO ()
forall a. ToJSON a => a -> [Char] -> IO ()
dumpTo UIDMap
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"
  UIDMap -> [Char] -> IO ()
forall a. ToJSON a => a -> [Char] -> IO ()
dumpTo UIDMap
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"

  System -> PrintingInformation -> [Char] -> IO ()
dumpChunkTables System
si PrintingInformation
pinfo ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
targetPath [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"tables.txt"

-- 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

dumpChunkTables :: System -> PrintingInformation -> TargetFile -> IO ()
dumpChunkTables :: System -> PrintingInformation -> [Char] -> IO ()
dumpChunkTables System
si PrintingInformation
pinfo [Char]
targetFile = do
  Handle
trg <- [Char] -> IOMode -> IO Handle
openFile [Char]
targetFile IOMode
WriteMode
  (Doc -> IO ()) -> [Doc] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (Handle -> [Char] -> IO ()
hPutStrLn Handle
trg ([Char] -> IO ()) -> (Doc -> [Char]) -> Doc -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Doc -> [Char]
render) ([Doc] -> IO ()) -> [Doc] -> IO ()
forall a b. (a -> b) -> a -> b
$ PrintingInformation -> UIDMap -> UIDMap -> [Doc]
printAllDebugInfo PrintingInformation
pinfo (System
si System -> Getting UIDMap System UIDMap -> UIDMap
forall s a. s -> Getting a s a -> a
^. Getting UIDMap System UIDMap
forall c. HasSystem c => Lens' c UIDMap
Lens' System UIDMap
refbyTable) (System
si System -> Getting UIDMap System UIDMap -> UIDMap
forall s a. s -> Getting a s a -> a
^. Getting UIDMap System UIDMap
forall c. HasSystem c => Lens' c UIDMap
Lens' System UIDMap
traceTable)
  Handle -> IO ()
hClose Handle
trg