{-# LANGUAGE TemplateHaskell #-}
module Main where

import Development.GitRev
import qualified Data.ByteString.Lazy.Char8 as BC
import qualified Data.Text.IO as T
import qualified Data.Text.Lazy.IO as TL
import System.IO
import System.Environment
import System.Exit

import DataFlow.Reader
import DataFlow.Core
import qualified DataFlow.Validation as V
import qualified DataFlow.DFD as DFD
import qualified DataFlow.SequenceDiagram as SEQ
import qualified DataFlow.Graphviz.Renderer as GVR
import qualified DataFlow.PlantUML.Renderer as PUR
import qualified DataFlow.Mustache.Renderer as MR
import qualified DataFlow.JSONGraphFormat.Renderer as JG

usage :: IO ()
usage = hPutStrLn stderr $ unlines [
    "Usage: dataflow command args*",
    "",
    "Commands",
    "--------",
    "dfd SRC               - outputs a DFD in the Graphviz DOT format",
    "seq SRC               - outputs a sequence diagram in PlantUML format",
    "template TEMPLATE SRC - renders the TEMPLATE using data from SRC",
    "json SRC              - outputs a sequence diagram in JSON Graph Format",
    "                        (http://jsongraphformat.info/)",
    "validate SRC          - validates the input",
    "",
    "--version             - display VCS information",
    "--help                - display this help message",
    "",
    "All commands print to stdout"
  ]

showErrors :: Show s => Either [s] v -> Either String v
showErrors = either (Left . unlines . map show) Right

readAndValidate :: FilePath -> IO (Either String Diagram)
readAndValidate path = do
  res <- readDiagramFile path
  case res of
    (Left err) -> return $ Left $ show err
    (Right d) -> return (showErrors $ V.validate d)

dfd :: FilePath -> IO ()
dfd path = do
  res <- readAndValidate path
  case res of
    (Left err) -> putStrLn err
    (Right d) -> putStr $ GVR.renderGraphviz $ DFD.asDFD d

seq' :: FilePath -> IO ()
seq' path = do
  res <- readAndValidate path
  case res of
    (Left err) -> putStrLn err
    (Right d) -> putStr $ PUR.renderPlantUML $ SEQ.asSequenceDiagram d

template :: FilePath -> FilePath -> IO ()
template tmplPath path = do
  res <- readAndValidate path
  tmplStr <- readFile tmplPath
  case res of
    (Left err) -> putStrLn err
    (Right d) -> either print T.putStr $ MR.renderTemplate tmplStr path d

json :: FilePath -> IO ()
json path = do
  res <- readAndValidate path
  case res of
    (Left err) -> putStrLn err
    (Right d) -> BC.putStrLn $ JG.renderJSONGraph d

validate :: FilePath -> IO ()
validate path = do
  res <- readAndValidate path
  case res of
    (Left err) -> putStrLn err
    (Right _) -> return ()

version :: IO ()
version = do
  putStrLn $ "Branch: " ++ $(gitBranch)
  putStrLn $ "Hash:   " ++ $(gitHash)

main :: IO ()
main = do
  args <- getArgs
  case args of
    ["dfd", path] -> dfd path
    ["seq", path] -> seq' path
    ["template", tmplPath, path] -> template tmplPath path
    ["json", path] -> json path
    ["validate", path] -> validate path
    ["--version"] -> version
    ["--help"] -> usage
    _ -> do hPutStrLn stderr "Invalid command!\n\nRun with --help to see usage."
            exitWith $ ExitFailure 1
