module Hix.Managed.Data.ManagedPackageProto where

import Data.Aeson (FromJSON (parseJSON), withObject, (.:))
import Data.List.Extra (nubOrdOn)
import qualified Data.Map.Strict as Map
import Distribution.Pretty (Pretty (pretty))
import Text.PrettyPrint (brackets, (<+>))

import Hix.Class.Map (nFromList)
import qualified Hix.Data.Dep
import Hix.Data.Dep (Dep)
import Hix.Data.Json (jsonParsec)
import qualified Hix.Data.PackageId
import Hix.Data.PackageId (PackageId (PackageId))
import Hix.Data.PackageName (LocalPackage (LocalPackage))
import Hix.Data.Version (Version)
import Hix.Managed.Data.Packages (Packages)
import Hix.Pretty (prettyL)

data ManagedPackageProto =
  ManagedPackageProto {
    ManagedPackageProto -> LocalPackage
name :: LocalPackage,
    ManagedPackageProto -> Version
version :: Version,
    ManagedPackageProto -> [Dep]
deps :: [Dep]
  }
  deriving stock (ManagedPackageProto -> ManagedPackageProto -> Bool
(ManagedPackageProto -> ManagedPackageProto -> Bool)
-> (ManagedPackageProto -> ManagedPackageProto -> Bool)
-> Eq ManagedPackageProto
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ManagedPackageProto -> ManagedPackageProto -> Bool
== :: ManagedPackageProto -> ManagedPackageProto -> Bool
$c/= :: ManagedPackageProto -> ManagedPackageProto -> Bool
/= :: ManagedPackageProto -> ManagedPackageProto -> Bool
Eq, Int -> ManagedPackageProto -> ShowS
[ManagedPackageProto] -> ShowS
ManagedPackageProto -> String
(Int -> ManagedPackageProto -> ShowS)
-> (ManagedPackageProto -> String)
-> ([ManagedPackageProto] -> ShowS)
-> Show ManagedPackageProto
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ManagedPackageProto -> ShowS
showsPrec :: Int -> ManagedPackageProto -> ShowS
$cshow :: ManagedPackageProto -> String
show :: ManagedPackageProto -> String
$cshowList :: [ManagedPackageProto] -> ShowS
showList :: [ManagedPackageProto] -> ShowS
Show, (forall x. ManagedPackageProto -> Rep ManagedPackageProto x)
-> (forall x. Rep ManagedPackageProto x -> ManagedPackageProto)
-> Generic ManagedPackageProto
forall x. Rep ManagedPackageProto x -> ManagedPackageProto
forall x. ManagedPackageProto -> Rep ManagedPackageProto x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. ManagedPackageProto -> Rep ManagedPackageProto x
from :: forall x. ManagedPackageProto -> Rep ManagedPackageProto x
$cto :: forall x. Rep ManagedPackageProto x -> ManagedPackageProto
to :: forall x. Rep ManagedPackageProto x -> ManagedPackageProto
Generic)

instance Pretty ManagedPackageProto where
  pretty :: ManagedPackageProto -> Doc
pretty ManagedPackageProto {[Dep]
Version
LocalPackage
name :: ManagedPackageProto -> LocalPackage
version :: ManagedPackageProto -> Version
deps :: ManagedPackageProto -> [Dep]
name :: LocalPackage
version :: Version
deps :: [Dep]
..} = PackageId -> Doc
forall a. Pretty a => a -> Doc
pretty PackageId {name :: PackageName
name = LocalPackage -> PackageName
forall a b. Coercible a b => a -> b
coerce LocalPackage
name, Version
version :: Version
version :: Version
version} Doc -> Doc -> Doc
<+> Doc -> Doc
brackets ([Dep] -> Doc
forall (t :: * -> *) a. (Pretty a, Foldable t) => t a -> Doc
prettyL [Dep]
deps)

instance FromJSON ManagedPackageProto where
  parseJSON :: Value -> Parser ManagedPackageProto
parseJSON =
    String
-> (Object -> Parser ManagedPackageProto)
-> Value
-> Parser ManagedPackageProto
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"ManagedPackageProto" \ Object
o -> do
      LocalPackage
name <- Object
o Object -> Key -> Parser LocalPackage
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"name"
      Version
version <- JsonParsec Version -> Version
forall a. JsonParsec a -> a
jsonParsec (JsonParsec Version -> Version)
-> Parser (JsonParsec Version) -> Parser Version
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Key -> Parser (JsonParsec Version)
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"version"
      [Dep]
deps <- (Dep -> PackageName) -> [Dep] -> [Dep]
forall b a. Ord b => (a -> b) -> [a] -> [a]
nubOrdOn (.package) ([Dep] -> [Dep]) -> Parser [Dep] -> Parser [Dep]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Key -> Parser [Dep]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"deps"
      pure ManagedPackageProto {[Dep]
Version
LocalPackage
name :: LocalPackage
version :: Version
deps :: [Dep]
name :: LocalPackage
version :: Version
deps :: [Dep]
..}

managedPackages :: Map (LocalPackage, Version) [Dep] -> Packages ManagedPackageProto
managedPackages :: Map (LocalPackage, Version) [Dep] -> Packages ManagedPackageProto
managedPackages Map (LocalPackage, Version) [Dep]
spec =
  [(LocalPackage, ManagedPackageProto)]
-> Packages ManagedPackageProto
forall map k v sort. NMap map k v sort => [(k, v)] -> map
nFromList (((LocalPackage, Version), [Dep])
-> (LocalPackage, ManagedPackageProto)
pkg (((LocalPackage, Version), [Dep])
 -> (LocalPackage, ManagedPackageProto))
-> [((LocalPackage, Version), [Dep])]
-> [(LocalPackage, ManagedPackageProto)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Map (LocalPackage, Version) [Dep]
-> [((LocalPackage, Version), [Dep])]
forall k a. Map k a -> [(k, a)]
Map.toList Map (LocalPackage, Version) [Dep]
spec)
  where
    pkg :: ((LocalPackage, Version), [Dep])
-> (LocalPackage, ManagedPackageProto)
pkg ((LocalPackage
name, Version
version), [Dep]
deps) =
      (LocalPackage
name, ManagedPackageProto {LocalPackage
name :: LocalPackage
name :: LocalPackage
name, Version
version :: Version
version :: Version
version, [Dep]
deps :: [Dep]
deps :: [Dep]
deps})