-- | Summary output type.

module OrgStat.Outputs.Summary
       ( genSummaryOutput
       ) where

import           Universum

import           Control.Lens                     (views)
import qualified Data.Attoparsec.ByteString.Char8 as A

import           OrgStat.Ast                      (orgTotalDuration)
import           OrgStat.Config                   (confReports, crName)
import           OrgStat.Helpers                  (resolveReport)
import           OrgStat.Outputs.Types            (SummaryOutput (..), SummaryParams (..))
import           OrgStat.Util                     (timeF)
import           OrgStat.WorkMonad                (WorkM, wcConfig)


-- | Tokenizes summary template string.
data InputToken
    = ReportTemplate Text -- ^ Valid template name surrounded by two '%'
    | OtherInfo Text          -- ^ Anything in between
    deriving Show

tokenize :: [Text] -> Text -> [InputToken]
tokenize keywords (encodeUtf8 -> input) =
    case A.parseOnly toplvl input of
      Left err  -> error $ fromString err
      Right res -> res
  where
    keyword = A.try $ do
        void $ A.char '%'
        between <- fromString <$> some (A.satisfy (/= '%'))
        void $ A.char '%'
        guard $ between `elem` keywords
        pure $ ReportTemplate between
    randomtext = do
        h <- A.anyChar
        t <- fromString <$> many (A.satisfy (/= '%'))
        pure $ OtherInfo $ fromString $ h:t
    toplvl = many (keyword <|> randomtext)

-- | Generates summary using provided params.
genSummaryOutput :: SummaryParams -> WorkM SummaryOutput
genSummaryOutput SummaryParams{..} = do
    declaredReports <- views wcConfig $ map crName . confReports
    let tokens = tokenize declaredReports spTemplate
    res <- fmap mconcat $ forM tokens $ \case
        OtherInfo t -> pure t
        ReportTemplate reportName -> do
            report <- resolveReport reportName
            pure $ timeF $ orgTotalDuration report
    pure $ SummaryOutput res