module Hix.Env where

import qualified Data.Text.IO as Text
import Path (Abs, Dir, Path)

import Hix.Component (targetComponent)
import qualified Hix.Data.ComponentConfig
import Hix.Data.ComponentConfig (EnvRunner (EnvRunner), PackagesConfig, TargetOrDefault (DefaultTarget, ExplicitTarget))
import Hix.Error (Error (EnvError), pathText)
import qualified Hix.Data.GhciConfig
import qualified Hix.Data.Options as Options
import Hix.Data.Options (EnvRunnerOptions, TargetSpec)
import Hix.Data.PackageName (PackageName)
import Hix.Json (jsonConfigE)
import Hix.Data.Monad (M)

-- TODO when there is a solution for default command env fallback configuration, the DefaultTarget case must return
-- Nothing when the config requests it
componentRunner ::
  Maybe (Path Abs Dir) ->
  Maybe PackageName ->
  PackagesConfig ->
  TargetSpec ->
  M (Maybe EnvRunner)
componentRunner :: Maybe (Path Abs Dir)
-> Maybe PackageName
-> PackagesConfig
-> TargetSpec
-> M (Maybe EnvRunner)
componentRunner Maybe (Path Abs Dir)
cliRoot Maybe PackageName
defaultPkg PackagesConfig
config TargetSpec
spec =
  Maybe (Path Abs Dir)
-> Maybe PackageName
-> PackagesConfig
-> TargetSpec
-> M TargetOrDefault
targetComponent Maybe (Path Abs Dir)
cliRoot Maybe PackageName
defaultPkg PackagesConfig
config TargetSpec
spec M TargetOrDefault
-> (TargetOrDefault -> Maybe EnvRunner) -> M (Maybe EnvRunner)
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \case
    ExplicitTarget Target
t -> Target
t.component.runner
    DefaultTarget Target
t -> Target
t.component.runner
    TargetOrDefault
_ -> Maybe EnvRunner
forall a. Maybe a
Nothing

envRunner :: EnvRunnerOptions -> M EnvRunner
envRunner :: EnvRunnerOptions -> M EnvRunner
envRunner EnvRunnerOptions
opts = do
  EnvConfig
config <- (Text -> Error) -> Either EnvConfig JsonConfig -> M EnvConfig
forall a.
FromJSON a =>
(Text -> Error) -> Either a JsonConfig -> M a
jsonConfigE Text -> Error
EnvError EnvRunnerOptions
opts.config
  let runner :: TargetSpec -> M (Maybe EnvRunner)
runner = Maybe (Path Abs Dir)
-> Maybe PackageName
-> PackagesConfig
-> TargetSpec
-> M (Maybe EnvRunner)
componentRunner EnvRunnerOptions
opts.root EnvConfig
config.mainPackage EnvConfig
config.packages
  EnvRunner -> Maybe EnvRunner -> EnvRunner
forall a. a -> Maybe a -> a
fromMaybe EnvConfig
config.defaultEnv (Maybe EnvRunner -> EnvRunner)
-> (Maybe (Maybe EnvRunner) -> Maybe EnvRunner)
-> Maybe (Maybe EnvRunner)
-> EnvRunner
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe (Maybe EnvRunner) -> Maybe EnvRunner
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join (Maybe (Maybe EnvRunner) -> EnvRunner)
-> M (Maybe (Maybe EnvRunner)) -> M EnvRunner
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (TargetSpec -> M (Maybe EnvRunner))
-> Maybe TargetSpec -> M (Maybe (Maybe EnvRunner))
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> Maybe a -> f (Maybe b)
traverse TargetSpec -> M (Maybe EnvRunner)
runner EnvRunnerOptions
opts.component

printEnvRunner :: EnvRunnerOptions -> M ()
printEnvRunner :: EnvRunnerOptions -> M ()
printEnvRunner EnvRunnerOptions
opts = do
  EnvRunner Path Abs File
runner <- EnvRunnerOptions -> M EnvRunner
envRunner EnvRunnerOptions
opts
  IO () -> M ()
forall a. IO a -> M a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Text -> IO ()
Text.putStrLn (Path Abs File -> Text
forall b t. Path b t -> Text
pathText Path Abs File
runner))