content: module Types (module Types) where
  
  import Data.Aeson (FromJSON (..), Value (..))
  import Data.Aeson.Key (toString)
  import Data.Aeson.KeyMap (toList)
  import Data.Map (Map)
  import Data.Map qualified as Map
  import Data.Sequence (Seq (..))
  import Data.Text (Text, pack)
  import GHC.Generics (Generic)
  
  data Context = Plain Text | Ref Text Text deriving (Eq, Ord)
  
  instance FromJSON Context where
      parseJSON (String t) = pure $ Plain t
      parseJSON (Object o) | [(k, String v)] <- toList o = pure $ Ref (pack $ toString k) v
      parseJSON _ = fail "Invalid context"
  
  data LogMessage = LogMessage
      { context :: Seq Context
      , message :: Value
      }
      deriving (Generic, FromJSON)
  
  type AbortKey = (Text, Text)
  
  countAborts ::
      (Map AbortKey Int, Map Text (Text, Text)) ->
      LogMessage ->
      (Map AbortKey Int, Map Text (Text, Text))
  countAborts maps@(countMap, ruleMap) LogMessage{context, message} = case context of
      (_ :|> Ref "rewrite" ruleId :|> Plain reason :|> Plain "abort") -> increment reason ruleId
      (_ :|> Ref "function" ruleId :|> Plain "failure" :|> Plain "break") -> increment "failure" ruleId
      (_ :|> Ref "simplification" ruleId :|> Plain "failure" :|> Plain "break") -> increment "failure" ruleId
      (_ :|> Ref "function" ruleId :|> Plain "match" :|> Plain "failure" :|> Plain "break") -> increment "failure" ruleId
      (_ :|> Ref "simplification" ruleId :|> Plain "match" :|> Plain "failure" :|> Plain "break") -> increment "failure" ruleId
      (_ :|> Ref "rewrite" ruleId :|> Plain "detail") | String ruleLoc <- message -> (countMap, Map.insert ruleId ("rewrite", ruleLoc) ruleMap)
      (_ :|> Ref "function" ruleId :|> Plain "detail") | String ruleLoc <- message -> (countMap, Map.insert ruleId ("function", ruleLoc) ruleMap)
      (_ :|> Ref "simplification" ruleId :|> Plain "detail") | String ruleLoc <- message -> (countMap, Map.insert ruleId ("simplification", ruleLoc) ruleMap)
      _ -> maps
    where
      increment rsn rid = (Map.alter (maybe (Just 1) (Just . (+ 1))) (rid, rsn) countMap, ruleMap)
  