{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE ConstraintKinds #-}

module Types
    ( Options(..)
    , AppConfig
    , AppError(..)
    , App(..)
    ) where

import Control.Monad.Except (ExceptT, MonadError)
import Control.Monad.Reader (MonadIO, MonadReader, ReaderT)
import Unused.CLI (SearchRunner)
import Unused.Cache (FingerprintOutcome)
import Unused.Grouping (CurrentGrouping)
import Unused.ResultsClassifier (ParseConfigError)
import Unused.TagsSource (TagSearchOutcome)
import Unused.TermSearch (SearchBackend)
import Unused.Types (RemovalLikelihood)

data Options = Options
    { oSearchRunner :: SearchRunner
    , oSingleOccurrenceMatches :: Bool
    , oLikelihoods :: [RemovalLikelihood]
    , oAllLikelihoods :: Bool
    , oIgnoredPaths :: [String]
    , oGrouping :: CurrentGrouping
    , oWithoutCache :: Bool
    , oFromStdIn :: Bool
    , oCommitCount :: Maybe Int
    , oSearchBackend :: SearchBackend
    }

type AppConfig = MonadReader Options

data AppError
    = TagError TagSearchOutcome
    | InvalidConfigError [ParseConfigError]
    | CacheError FingerprintOutcome

newtype App a = App
    { runApp :: ReaderT Options (ExceptT AppError IO) a
    } deriving (Monad, Functor, Applicative, AppConfig, MonadError AppError, MonadIO)
