{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE RecordWildCards #-}

-- | Build configuration
module Stack.Config.Build where

import           Stack.Prelude
import           Stack.Types.Config

-- | Interprets BuildOptsMonoid options.
buildOptsFromMonoid :: BuildOptsMonoid -> BuildOpts
buildOptsFromMonoid BuildOptsMonoid{..} = BuildOpts
    { boptsLibProfile = fromFirstFalse
          (buildMonoidLibProfile <>
           FirstFalse (if tracing || profiling then Just True else Nothing))
    , boptsExeProfile = fromFirstFalse
          (buildMonoidExeProfile <>
           FirstFalse (if tracing || profiling then Just True else Nothing))
    , boptsLibStrip = fromFirstTrue
          (buildMonoidLibStrip <>
           FirstTrue (if noStripping then Just False else Nothing))
    , boptsExeStrip = fromFirstTrue
          (buildMonoidExeStrip <>
           FirstTrue (if noStripping then Just False else Nothing))
    , boptsHaddock = fromFirstFalse buildMonoidHaddock
    , boptsHaddockOpts = haddockOptsFromMonoid buildMonoidHaddockOpts
    , boptsOpenHaddocks = fromFirstFalse buildMonoidOpenHaddocks
    , boptsHaddockDeps = getFirst buildMonoidHaddockDeps
    , boptsHaddockInternal = fromFirstFalse buildMonoidHaddockInternal
    , boptsHaddockHyperlinkSource = fromFirstTrue buildMonoidHaddockHyperlinkSource
    , boptsInstallExes = fromFirstFalse buildMonoidInstallExes
    , boptsInstallCompilerTool = fromFirstFalse buildMonoidInstallCompilerTool
    , boptsPreFetch = fromFirstFalse buildMonoidPreFetch
    , boptsKeepGoing = getFirst buildMonoidKeepGoing
    , boptsKeepTmpFiles = fromFirstFalse buildMonoidKeepTmpFiles
    , boptsForceDirty = fromFirstFalse buildMonoidForceDirty
    , boptsTests = fromFirstFalse buildMonoidTests
    , boptsTestOpts =
          testOptsFromMonoid buildMonoidTestOpts additionalArgs
    , boptsBenchmarks = fromFirstFalse buildMonoidBenchmarks
    , boptsBenchmarkOpts =
          benchmarkOptsFromMonoid buildMonoidBenchmarkOpts additionalArgs
    , boptsReconfigure = fromFirstFalse buildMonoidReconfigure
    , boptsCabalVerbose = fromFirstFalse buildMonoidCabalVerbose
    , boptsSplitObjs = fromFirstFalse buildMonoidSplitObjs
    , boptsSkipComponents = buildMonoidSkipComponents
    , boptsInterleavedOutput = fromFirstTrue buildMonoidInterleavedOutput
    , boptsDdumpDir = getFirst buildMonoidDdumpDir
    }
  where
    -- These options are not directly used in bopts, instead they
    -- transform other options.
    tracing = getAny buildMonoidTrace
    profiling = getAny buildMonoidProfile
    noStripping = getAny buildMonoidNoStrip
    -- Additional args for tracing / profiling
    additionalArgs =
        if tracing || profiling
            then Just $ "+RTS" : catMaybes [trac, prof, Just "-RTS"]
            else Nothing
    trac =
        if tracing
            then Just "-xc"
            else Nothing
    prof =
        if profiling
            then Just "-p"
            else Nothing

haddockOptsFromMonoid :: HaddockOptsMonoid -> HaddockOpts
haddockOptsFromMonoid HaddockOptsMonoid{..} =
    defaultHaddockOpts
    {hoAdditionalArgs = hoMonoidAdditionalArgs}

testOptsFromMonoid :: TestOptsMonoid -> Maybe [String] -> TestOpts
testOptsFromMonoid TestOptsMonoid{..} madditional =
    defaultTestOpts
    { toRerunTests = fromFirstTrue toMonoidRerunTests
    , toAdditionalArgs = fromMaybe [] madditional <> toMonoidAdditionalArgs
    , toCoverage = fromFirstFalse toMonoidCoverage
    , toDisableRun = fromFirstFalse toMonoidDisableRun
    , toMaximumTimeSeconds = fromFirst (toMaximumTimeSeconds defaultTestOpts) toMonoidMaximumTimeSeconds
    }

benchmarkOptsFromMonoid :: BenchmarkOptsMonoid -> Maybe [String] -> BenchmarkOpts
benchmarkOptsFromMonoid BenchmarkOptsMonoid{..} madditional =
    defaultBenchmarkOpts
    { beoAdditionalArgs =
          fmap (\args -> unwords args <> " ") madditional <>
          getFirst beoMonoidAdditionalArgs
    , beoDisableRun = fromFirst
          (beoDisableRun defaultBenchmarkOpts)
          beoMonoidDisableRun
    }
