packages feed

schedule-planner-1.0.0.0: src/Main.hs

{-# LANGUAGE OverloadedStrings #-}
{-|
Module      : $Header$
Description : Interface for schedule-planner
Copyright   : (c) Justus Adam, 2015
License     : LGPL-3
Maintainer  : development@justusadam.com
Stability   : experimental
Portability : POSIX

main function and outside communication for this software.
This module takes care of reading all input and checking for correctness
as well as providing useful feedback upon encountering errors.
-}
module Main (main) where


import           Data.Text                  (pack)
import           Data.ByteString.Lazy       (readFile)
import           Options                    (Options, defineOption,
                                             defineOptions, optionDefault,
                                             optionDescription, optionLongFlags,
                                             optionShortFlags, optionType_bool,
                                             optionType_maybe, optionType_int,
                                             optionType_string, runSubcommand,
                                             subcommand)
import           Prelude                    hiding (readFile)
import           SchedulePlanner.App        (reportAndPrint, serverCalculation)
import qualified SchedulePlanner.Server     as Server (server)


stdFileName :: String
stdFileName = "testsuite/test.json"


-- |Temporary constant, should be in call args eventually
outputFormatDefault :: String
outputFormatDefault = "print"


defaultServerPort :: Int
defaultServerPort = 7097


data CommonOptions = CommonOptions


instance Options CommonOptions where
  defineOptions = pure CommonOptions

-- |Command line options to choose from
data DirectCallOptions = DirectCallOptions { outputFile   :: Maybe String
                                           , inputFile    :: String
                                           , outputFormat :: String
                                           , verbocity    :: Bool
                                           } deriving (Show)


instance Options DirectCallOptions where
  defineOptions = DirectCallOptions
    <$> defineOption
          (optionType_maybe optionType_string)
          (\o -> o { optionLongFlags   = ["output-file"]
                   , optionShortFlags  = "o"
                   , optionDescription = "print output to this file instead of stdout"
                   , optionDefault     = Nothing
                   })
    <*> defineOption
          optionType_string
          (\o -> o { optionDefault     = stdFileName
                   , optionLongFlags   = ["input-file"]
                   , optionShortFlags  = "i"
                   , optionDescription = "read input from this file"
                   })
    <*> defineOption
          optionType_string
          (\o -> o { optionDefault     = outputFormatDefault
                   , optionLongFlags   = ["output-format"]
                   , optionShortFlags  = "f"
                   , optionDescription = "set the output format"
                   })
    <*> defineOption
          optionType_bool
          (\o -> o { optionDefault     = False
                   , optionLongFlags   = ["verbose"]
                   , optionShortFlags  = "v"
                   , optionDescription = "Print extra information"
                   })


data ServerOptions = ServerOptions { port :: Int }


instance Options ServerOptions where
  defineOptions = ServerOptions
    <$> defineOption
          optionType_int
          (\o -> o { optionLongFlags   = ["port"]
                   , optionShortFlags  = "p"
                   , optionDescription = "The port to run the server on"
                   , optionDefault     = defaultServerPort
                   })


{-|
  main function. Handles reading command line arguments, the json input
  and starts execution.
-}
main :: IO()
main =
  runSubcommand
    [ subcommand "calc" directCall
    , subcommand "serve" serverMain
    ]

directCall :: CommonOptions -> DirectCallOptions -> [String] -> IO ()
directCall
  _
  ( DirectCallOptions
      { inputFile = ifile
      , outputFormat = outForm
      , verbocity = v
      })
  _
  = readFile ifile >>=
        reportAndPrint (pack outForm) v


serverMain :: CommonOptions -> ServerOptions -> [String] -> IO ()
serverMain _ (ServerOptions { port = p }) _ = Server.server p serverCalculation