content: {-# LANGUAGE NoMonomorphismRestriction, FlexibleContexts, TypeFamilies #-}
  module Main
    (main
    , CmdLineOptions(..)) where
  
  import Prelude hiding (return)
  
  -- Note: (#) and (&) are hidden in all Glance source files, since they would
  -- require a special case when translating when Glance is run on its own source
  -- code.
  import qualified Diagrams.Prelude as Dia hiding ((#), (&))
  
  import qualified Language.Haskell.Exts as Exts
  
  -- Options.Applicative does not seem to work qualified
  import Options.Applicative(header, progDesc, fullDesc, helper, info
                            , defaultPrefs, customExecParser, help, short, switch
                            , metavar, auto, argument, str, prefShowHelpOnError
                            , Parser)
  
  import Icons(ColorStyle(..), colorScheme, multilineComment)
  import Rendering(renderIngSyntaxGraph)
  import Translate(translateModuleToCollapsedGraphs)
  import Util(customRenderSVG)
  
  {-# ANN module "HLint: ignore Unnecessary hiding" #-}
  
  data CmdLineOptions = CmdLineOptions {
    cmdInputFilename :: String,
    cmdOutputFilename :: String,
    cmdImageWidth :: Double,
    cmdIncludeComments :: Bool
    }
  
  optionParser :: Parser CmdLineOptions
  optionParser = CmdLineOptions
    <$> argument str (metavar "INPUT_FILE" Dia.<> help "Input .hs filename")
    <*> argument str (metavar "OUTPUT_FILE" Dia.<> help "Output .svg filename")
    <*> argument auto (metavar "IMAGE_WIDTH" Dia.<> help "Output image width")
    <*> switch
    (short 'c' Dia.<> help "Include comments between top level declarations.")
  
  renderFile :: CmdLineOptions -> IO ()
  renderFile (CmdLineOptions
               inputFilename
               outputFilename
               imageWidth
               includeComments)
    = do
    putStrLn $ "Translating file " ++ inputFilename ++ " into a Glance image."
    parseResult <- Exts.parseFileWithComments
      (Exts.defaultParseMode {
          Exts.extensions = [Exts.EnableExtension Exts.MultiParamTypeClasses
                            , Exts.EnableExtension Exts.FlexibleContexts]
          , Exts.parseFilename = inputFilename
          })
      inputFilename
    let
      (parsedModule, comments) = Exts.fromParseResult parseResult
      drawings = translateModuleToCollapsedGraphs parsedModule
    --print parsedModule
    --print "\n\n"
    --print drawings
  
    diagrams <- traverse (renderIngSyntaxGraph "") drawings
    let
      commentsInBoxes
        = fmap
          (\(Exts.Comment _ _ c) ->
              Dia.alignL $ multilineComment Dia.white (Dia.opaque Dia.white) c)
          comments
      diagramsAndComments
        = Dia.vsep 2 $ zipWith
          (\x y -> x Dia.=== Dia.strutY 0.4 Dia.=== y)
          commentsInBoxes
          (fmap Dia.alignL diagrams)
      justDiagrams = Dia.vsep 1 $ fmap Dia.alignL diagrams
      diagramsAndMaybeComments
        = if includeComments then diagramsAndComments else justDiagrams
    --print comments
  
      finalDia = Dia.bgFrame 1 (backgroundC colorScheme) diagramsAndMaybeComments
    customRenderSVG outputFilename (Dia.mkWidth imageWidth) finalDia
    putStrLn $ "Successfully wrote " ++ outputFilename
  
  translateFileMain :: IO ()
  translateFileMain = customExecParser parserPrefs  opts >>= renderFile where
  
    parserPrefs = defaultPrefs{
      prefShowHelpOnError = True
      }
  
    opts = info (helper <*> optionParser)
      (fullDesc
      Dia.<> progDesc "Translate a Haskell source file (.hs) into an SVG image."
      Dia.<> header "Glance - a visual representation of Haskell")
  
  main :: IO ()
  main = translateFileMain
  