{-# LANGUAGE DeriveAnyClass             #-}
{-# LANGUAGE DerivingStrategies         #-}
{-# LANGUAGE DerivingVia                #-}
{-# LANGUAGE GeneralisedNewtypeDeriving #-}
{-# LANGUAGE LambdaCase                 #-}
{-# LANGUAGE MultiWayIf                 #-}
{-# LANGUAGE OverloadedStrings          #-}
{-# LANGUAGE RecordWildCards            #-}
{-# LANGUAGE ScopedTypeVariables        #-}
{-# LANGUAGE StandaloneDeriving         #-}
{-# LANGUAGE TupleSections              #-}

module HS.Cfg.Types where

import           Data.Default
import           Data.Map(Map)
import qualified Data.Map           as Map
import           Data.Maybe
import qualified Data.Text          as T
import           Fmt
import           HS.Managers.Types
import           HS.Types.CompilerTool
import           HS.Types.InstallMode
import           HS.Types.Manager
import           System.FilePath
import           Text.Enum.Text


data Cfg =
  Cfg
    { Cfg -> Managers
_cfg_managers      :: Managers
    , Cfg -> InstallMode
_cfg_mode          :: InstallMode
    , Cfg -> CompilerVersion
_cfg_compiler      :: CompilerVersion
    , Cfg -> Map Compiler Installation
_cfg_installations :: Map Compiler Installation
    }
  deriving (Int -> Cfg -> ShowS
[Cfg] -> ShowS
Cfg -> String
(Int -> Cfg -> ShowS)
-> (Cfg -> String) -> ([Cfg] -> ShowS) -> Show Cfg
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Cfg] -> ShowS
$cshowList :: [Cfg] -> ShowS
show :: Cfg -> String
$cshow :: Cfg -> String
showsPrec :: Int -> Cfg -> ShowS
$cshowsPrec :: Int -> Cfg -> ShowS
Show)

data Installation =
  Installation
    { Installation -> CompilerVersion
_iln_compiler   :: CompilerVersion
    , Installation -> Manager
_iln_manager    :: Manager
    , Installation -> String
_iln_dir        :: FilePath
    }
  deriving (Int -> Installation -> ShowS
[Installation] -> ShowS
Installation -> String
(Int -> Installation -> ShowS)
-> (Installation -> String)
-> ([Installation] -> ShowS)
-> Show Installation
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Installation] -> ShowS
$cshowList :: [Installation] -> ShowS
show :: Installation -> String
$cshow :: Installation -> String
showsPrec :: Int -> Installation -> ShowS
$cshowsPrec :: Int -> Installation -> ShowS
Show)

newtype Managers = Managers { Managers -> [Manager]
getManagers :: [Manager] }
  deriving stock (Managers -> Managers -> Bool
(Managers -> Managers -> Bool)
-> (Managers -> Managers -> Bool) -> Eq Managers
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Managers -> Managers -> Bool
$c/= :: Managers -> Managers -> Bool
== :: Managers -> Managers -> Bool
$c== :: Managers -> Managers -> Bool
Eq,Eq Managers
Eq Managers
-> (Managers -> Managers -> Ordering)
-> (Managers -> Managers -> Bool)
-> (Managers -> Managers -> Bool)
-> (Managers -> Managers -> Bool)
-> (Managers -> Managers -> Bool)
-> (Managers -> Managers -> Managers)
-> (Managers -> Managers -> Managers)
-> Ord Managers
Managers -> Managers -> Bool
Managers -> Managers -> Ordering
Managers -> Managers -> Managers
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Managers -> Managers -> Managers
$cmin :: Managers -> Managers -> Managers
max :: Managers -> Managers -> Managers
$cmax :: Managers -> Managers -> Managers
>= :: Managers -> Managers -> Bool
$c>= :: Managers -> Managers -> Bool
> :: Managers -> Managers -> Bool
$c> :: Managers -> Managers -> Bool
<= :: Managers -> Managers -> Bool
$c<= :: Managers -> Managers -> Bool
< :: Managers -> Managers -> Bool
$c< :: Managers -> Managers -> Bool
compare :: Managers -> Managers -> Ordering
$ccompare :: Managers -> Managers -> Ordering
$cp1Ord :: Eq Managers
Ord,Int -> Managers -> ShowS
[Managers] -> ShowS
Managers -> String
(Int -> Managers -> ShowS)
-> (Managers -> String) -> ([Managers] -> ShowS) -> Show Managers
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Managers] -> ShowS
$cshowList :: [Managers] -> ShowS
show :: Managers -> String
$cshow :: Managers -> String
showsPrec :: Int -> Managers -> ShowS
$cshowsPrec :: Int -> Managers -> ShowS
Show)

instance Buildable Installation where
  build :: Installation -> Builder
build Installation{String
CompilerVersion
Manager
_iln_dir :: String
_iln_manager :: Manager
_iln_compiler :: CompilerVersion
_iln_dir :: Installation -> String
_iln_manager :: Installation -> Manager
_iln_compiler :: Installation -> CompilerVersion
..} =
      Builder
"" Builder -> Builder -> Builder
forall b. FromBuilder b => Builder -> Builder -> b
+|Int -> Char -> CompilerVersion -> Builder
forall a. Buildable a => Int -> Char -> a -> Builder
padRightF Int
10 Char
' ' CompilerVersion
_iln_compilerBuilder -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+
      Builder
" "Builder -> Builder -> Builder
forall b. FromBuilder b => Builder -> Builder -> b
+|Int -> Char -> Manager -> Builder
forall a. Buildable a => Int -> Char -> a -> Builder
padRightF  Int
5 Char
' ' Manager
_iln_manager Builder -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+
      Builder
" "Builder -> Builder -> Builder
forall b. FromBuilder b => Builder -> Builder -> b
+|                 String
_iln_dir     String -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+
      Builder
""

instance Buildable Managers where
  build :: Managers -> Builder
build = [Manager] -> Builder
forall (f :: * -> *) a. (Foldable f, Buildable a) => f a -> Builder
unwordsF ([Manager] -> Builder)
-> (Managers -> [Manager]) -> Managers -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Managers -> [Manager]
getManagers

instance TextParsable Managers where
  parseText :: Text -> Possibly Managers
parseText = ([Manager] -> Managers)
-> Either String [Manager] -> Possibly Managers
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [Manager] -> Managers
Managers (Either String [Manager] -> Possibly Managers)
-> (Text -> Either String [Manager]) -> Text -> Possibly Managers
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Either String Manager)
-> [Text] -> Either String [Manager]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Text -> Either String Manager
forall a. TextParsable a => Text -> Possibly a
parseText ([Text] -> Either String [Manager])
-> (Text -> [Text]) -> Text -> Either String [Manager]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Text]
T.words

instance Default Managers where
  def :: Managers
def = [Manager] -> Managers
Managers [Manager
stack,Manager
ghcup]

_iln_executable :: Installation -> FilePath
_iln_executable :: Installation -> String
_iln_executable Installation
iln = Installation -> ToolName -> String
_iln_tool_executable Installation
iln ToolName
TN_ghc

_iln_tool_executable :: Installation -> ToolName -> FilePath
_iln_tool_executable :: Installation -> ToolName -> String
_iln_tool_executable Installation
iln ToolName
tnm = Installation -> String
_iln_bin Installation
iln String -> ShowS
</> (Builder -> String
forall b. FromBuilder b => Builder -> b
fmt (Builder -> String) -> Builder -> String
forall a b. (a -> b) -> a -> b
$ ToolName -> Builder
forall p. Buildable p => p -> Builder
build ToolName
tnm)

_iln_bin :: Installation -> FilePath
_iln_bin :: Installation -> String
_iln_bin Installation{String
CompilerVersion
Manager
_iln_dir :: String
_iln_manager :: Manager
_iln_compiler :: CompilerVersion
_iln_dir :: Installation -> String
_iln_manager :: Installation -> Manager
_iln_compiler :: Installation -> CompilerVersion
..} = String
_iln_dir String -> ShowS
</> String
"bin"

resolveCompilerVersion :: Cfg -> Compiler -> CompilerVersion
resolveCompilerVersion :: Cfg -> Compiler -> CompilerVersion
resolveCompilerVersion Cfg
cfg Compiler
cp = CompilerVersion -> Maybe CompilerVersion -> CompilerVersion
forall a. a -> Maybe a -> a
fromMaybe CompilerVersion
_cfg_compiler (Maybe CompilerVersion -> CompilerVersion)
-> Maybe CompilerVersion -> CompilerVersion
forall a b. (a -> b) -> a -> b
$ Compiler -> Maybe CompilerVersion
compilerVersion Compiler
cp
  where
    Cfg{Map Compiler Installation
CompilerVersion
InstallMode
Managers
_cfg_installations :: Map Compiler Installation
_cfg_mode :: InstallMode
_cfg_managers :: Managers
_cfg_compiler :: CompilerVersion
_cfg_installations :: Cfg -> Map Compiler Installation
_cfg_compiler :: Cfg -> CompilerVersion
_cfg_mode :: Cfg -> InstallMode
_cfg_managers :: Cfg -> Managers
..} = Cfg
cfg


----------------------------------------------------------------------------------------------------
-- testing tools
----------------------------------------------------------------------------------------------------

ghc, ghc_8'10'4, ghc_9'0'2 :: Compiler
ghc :: Compiler
ghc        = Maybe CompilerVersion -> Compiler
Compiler   Maybe CompilerVersion
forall a. Maybe a
Nothing
ghc_8'10'4 :: Compiler
ghc_8'10'4 = Maybe CompilerVersion -> Compiler
Compiler (Maybe CompilerVersion -> Compiler)
-> Maybe CompilerVersion -> Compiler
forall a b. (a -> b) -> a -> b
$ CompilerVersion -> Maybe CompilerVersion
forall a. a -> Maybe a
Just CompilerVersion
v8'10'4
ghc_9'0'2 :: Compiler
ghc_9'0'2  = Maybe CompilerVersion -> Compiler
Compiler (Maybe CompilerVersion -> Compiler)
-> Maybe CompilerVersion -> Compiler
forall a b. (a -> b) -> a -> b
$ CompilerVersion -> Maybe CompilerVersion
forall a. a -> Maybe a
Just CompilerVersion
v9'0'2

v8'10'4, v9'0'2 :: CompilerVersion
v8'10'4 :: CompilerVersion
v8'10'4 = (Int, Int, Int) -> CompilerVersion
CompilerVersion (Int
8,Int
10,Int
4)
v9'0'2 :: CompilerVersion
v9'0'2  = (Int, Int, Int) -> CompilerVersion
CompilerVersion (Int
9,Int
0,Int
2)

testCfg :: Cfg
testCfg :: Cfg
testCfg =
    Cfg :: Managers
-> InstallMode
-> CompilerVersion
-> Map Compiler Installation
-> Cfg
Cfg
      { _cfg_managers :: Managers
_cfg_managers      = [Manager] -> Managers
Managers [Manager
stack,Manager
ghcup]
      , _cfg_mode :: InstallMode
_cfg_mode          = InstallMode
forall a. Default a => a
def
      , _cfg_compiler :: CompilerVersion
_cfg_compiler      = CompilerVersion
v8'10'4
      , _cfg_installations :: Map Compiler Installation
_cfg_installations = [(Compiler, Installation)] -> Map Compiler Installation
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList [(Compiler, Installation)]
as
      }
  where
    as :: [(Compiler,Installation)]
    as :: [(Compiler, Installation)]
as =
      [ (,) Compiler
ghc        (Installation -> (Compiler, Installation))
-> Installation -> (Compiler, Installation)
forall a b. (a -> b) -> a -> b
$ CompilerVersion -> Manager -> String -> Installation
Installation CompilerVersion
v8'10'4 Manager
stack String
"/Users/chris/.stack/programs/x86_64-osx/ghc-8.10.4"
      , (,) Compiler
ghc_8'10'4 (Installation -> (Compiler, Installation))
-> Installation -> (Compiler, Installation)
forall a b. (a -> b) -> a -> b
$ CompilerVersion -> Manager -> String -> Installation
Installation CompilerVersion
v8'10'4 Manager
stack String
"/Users/chris/.stack/programs/x86_64-osx/ghc-8.10.4"
      , (,) Compiler
ghc_9'0'2  (Installation -> (Compiler, Installation))
-> Installation -> (Compiler, Installation)
forall a b. (a -> b) -> a -> b
$ CompilerVersion -> Manager -> String -> Installation
Installation CompilerVersion
v9'0'2  Manager
ghcup String
"/Users/chris/.ghcup/ghc/9.0.1"
      ]