content: {-# LANGUAGE DeriveGeneric      #-}
  {-# LANGUAGE DerivingStrategies #-}
  
  -- |
  -- Module    : Aura.Settings
  -- Copyright : (c) Colin Woodbury, 2012 - 2024
  -- License   : GPL3
  -- Maintainer: Colin Woodbury <colin@fosskers.ca>
  --
  -- Definition of the runtime environment.
  
  module Aura.Settings
    ( Settings(..)
    , logFuncOfL
      -- * Aura Configuration
    , BuildConfig(..), BuildSwitch(..)
    , buildPathOfL, buildUserOfL, buildSwitchesOfL, allsourcePathOfL, vcsPathOfL
    , switch
    , Truncation(..)
    , defaultBuildDir
      -- * Pacman Interop
    , CommonConfig(..), CommonSwitch(..)
    , cachePathOfL, logPathOfL
    , ColourMode(..)
    , shared
      -- * Makepkg Interop
    , Makepkg(..)
    ) where
  
  import           Aura.Types
  import           Network.HTTP.Client (Manager)
  import           RIO
  import qualified RIO.Set as S
  import qualified RIO.Text as T
  
  ---
  
  -- | How @-As@ should truncate its results.
  data Truncation = None | Head !Word | Tail !Word deriving (Eq, Show)
  
  -- | CLI flags that will be passed down to @makepkg@ when building packages.
  data Makepkg = IgnoreArch | AllSource | SkipInteg | SkipPGP | NoCheck
    deriving (Eq, Ord, Show)
  
  instance Flagable Makepkg where
    asFlag IgnoreArch = ["--ignorearch"]
    asFlag AllSource  = ["--allsource"]
    asFlag SkipInteg  = ["--skipinteg"]
    asFlag SkipPGP    = ["--skippgpcheck"]
    asFlag NoCheck    = ["--nocheck"]
  
  -- | Flags that are common to both Aura and Pacman.
  -- Aura will react to them, but also pass them through to `pacman`
  -- calls if necessary.
  data CommonConfig = CommonConfig
    { cachePathOf      :: !(Either FilePath FilePath)
    , configPathOf     :: !(Either FilePath FilePath)
    , logPathOf        :: !(Either FilePath FilePath)
    , commonSwitchesOf :: !(Set CommonSwitch) } deriving (Show, Generic)
  
  cachePathOfL :: Lens' CommonConfig (Either FilePath FilePath)
  cachePathOfL f cc = (\cp -> cc { cachePathOf = cp }) <$> f (cachePathOf cc)
  
  logPathOfL :: Lens' CommonConfig (Either FilePath FilePath)
  logPathOfL f cc = (\cp -> cc { logPathOf = cp }) <$> f (logPathOf cc)
  
  instance Flagable CommonConfig where
    asFlag (CommonConfig cap cop lfp cs) =
      either (const []) (\p -> ["--cachedir", T.pack p]) cap
      <> either (const []) (\p -> ["--config", T.pack p]) cop
      <> either (const []) (\p -> ["--logfile", T.pack p]) lfp
      <> asFlag cs
  
  -- | Yes/No-style switches that are common to both Aura and Pacman.
  -- Aura acts on them first, then passes them down to @pacman@ if necessary.
  data CommonSwitch = NoConfirm | NeededOnly | Debug | Colour !ColourMode | Overwrite !Text
    deriving (Eq, Ord, Show)
  
  instance Flagable CommonSwitch where
    asFlag NoConfirm     = ["--noconfirm"]
    asFlag NeededOnly    = ["--needed"]
    asFlag Debug         = ["--debug"]
    asFlag (Colour m)    = "--color" : asFlag m
    asFlag (Overwrite t) = "--overwrite" : asFlag t
  
  -- | Matches Pacman's colour options. `Auto` will ensure that text will only be coloured
  -- when the output target is a terminal.
  data ColourMode = Never | Always | Auto deriving (Eq, Ord, Show)
  
  instance Flagable ColourMode where
    asFlag Never  = ["never"]
    asFlag Always = ["always"]
    asFlag Auto   = ["auto"]
  
  -- | Settings unique to the AUR package building process.
  data BuildConfig = BuildConfig
    { makepkgFlagsOf  :: !(Set Makepkg)
    , buildPathOf     :: !(Maybe FilePath)
    , buildUserOf     :: !(Maybe User)
    , allsourcePathOf :: !(Maybe FilePath)
    , vcsPathOf       :: !(Maybe FilePath)
    , truncationOf    :: !Truncation  -- For `-As`
    , buildSwitchesOf :: !(Set BuildSwitch) } deriving (Show)
  
  buildPathOfL :: Lens' BuildConfig (Maybe FilePath)
  buildPathOfL f bc = (\bp -> bc { buildPathOf = bp }) <$> f (buildPathOf bc)
  
  buildUserOfL :: Lens' BuildConfig (Maybe User)
  buildUserOfL f bc = (\bu -> bc { buildUserOf = bu }) <$> f (buildUserOf bc)
  
  buildSwitchesOfL :: Lens' BuildConfig (Set BuildSwitch)
  buildSwitchesOfL f bc = (\bs -> bc { buildSwitchesOf = bs }) <$> f (buildSwitchesOf bc)
  
  allsourcePathOfL :: Lens' BuildConfig (Maybe FilePath)
  allsourcePathOfL f bc = (\pth -> bc { allsourcePathOf = pth }) <$> f (allsourcePathOf bc)
  
  vcsPathOfL :: Lens' BuildConfig (Maybe FilePath)
  vcsPathOfL f bc = (\pth -> bc { vcsPathOf = pth }) <$> f (vcsPathOf bc)
  
  -- | Extra options for customizing the build process.
  data BuildSwitch
    = AsDeps
    | DeleteBuildDir
    | DeleteMakeDeps
    | DiffPkgbuilds
    | DontSuppressMakepkg
    | DryRun
    | ForceBuilding
    | HotEdit
    | LowVerbosity
    | NoPkgbuildCheck
    | RebuildDevel
    | SkipDepCheck
    | SortAlphabetically  -- For `-As`
    deriving (Eq, Ord, Show)
  
  -- | Is some Aura-specific setting turned on for this run?
  switch :: Settings -> BuildSwitch -> Bool
  switch ss bs = S.member bs . buildSwitchesOf $ buildConfigOf ss
  
  -- | Is some Aura/Pacman common setting turned on for this run?
  shared :: Settings -> CommonSwitch -> Bool
  shared ss c = S.member c . commonSwitchesOf $ commonConfigOf ss
  
  -- | The global settings as set by the user with command-line flags.
  data Settings = Settings
    { managerOf      :: !Manager
    , envOf          :: !Environment
    , langOf         :: !Language
    , editorOf       :: !FilePath
    , isTerminal     :: !Bool
    , ignoresOf      :: !(Set PkgName)
    , commonConfigOf :: !CommonConfig
    , buildConfigOf  :: !BuildConfig
    , logLevelOf     :: !LogLevel
    , logFuncOf      :: !LogFunc }
    deriving stock (Generic)
  
  logFuncOfL :: Lens' Settings LogFunc
  logFuncOfL f s = (\lf -> s { logFuncOf = lf }) <$> f (logFuncOf s)
  
  -- | Unless otherwise specified, packages will be built within @/tmp@.
  defaultBuildDir :: FilePath
  defaultBuildDir = "/tmp"
  