module Imp.Type.Package where

import qualified Control.Monad as Monad
import qualified Control.Monad.Catch as Exception
import qualified Data.Map as Map
import qualified Imp.Exception.InvalidPackage as InvalidPackage
import qualified Imp.Type.PackageName as PackageName
import qualified Imp.Type.Target as Target

data Package = Package
  { Package -> Target
module_ :: Target.Target,
    Package -> PackageName
package :: PackageName.PackageName
  }
  deriving (Package -> Package -> Bool
(Package -> Package -> Bool)
-> (Package -> Package -> Bool) -> Eq Package
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Package -> Package -> Bool
== :: Package -> Package -> Bool
$c/= :: Package -> Package -> Bool
/= :: Package -> Package -> Bool
Eq, Int -> Package -> ShowS
[Package] -> ShowS
Package -> String
(Int -> Package -> ShowS)
-> (Package -> String) -> ([Package] -> ShowS) -> Show Package
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Package -> ShowS
showsPrec :: Int -> Package -> ShowS
$cshow :: Package -> String
show :: Package -> String
$cshowList :: [Package] -> ShowS
showList :: [Package] -> ShowS
Show)

fromString :: (Exception.MonadThrow m) => String -> m Package
fromString :: forall (m :: * -> *). MonadThrow m => String -> m Package
fromString String
string = do
  let (String
before, String
after) = (Char -> Bool) -> String -> (String, String)
forall a. (a -> Bool) -> [a] -> ([a], [a])
break (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
':') String
string
  Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
Monad.when (String -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
after) (m () -> m ())
-> (InvalidPackage -> m ()) -> InvalidPackage -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. InvalidPackage -> m ()
forall e a. (HasCallStack, Exception e) => e -> m a
forall (m :: * -> *) e a.
(MonadThrow m, HasCallStack, Exception e) =>
e -> m a
Exception.throwM (InvalidPackage -> m ()) -> InvalidPackage -> m ()
forall a b. (a -> b) -> a -> b
$ String -> InvalidPackage
InvalidPackage.new String
string
  Target
mdl <- String -> m Target
forall (m :: * -> *). MonadThrow m => String -> m Target
Target.fromString String
before
  PackageName
pkg <- String -> m PackageName
forall (m :: * -> *). MonadThrow m => String -> m PackageName
PackageName.fromString (String -> m PackageName) -> ShowS -> String -> m PackageName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> ShowS
forall a. Int -> [a] -> [a]
drop Int
1 (String -> m PackageName) -> String -> m PackageName
forall a b. (a -> b) -> a -> b
$ String
after
  Package -> m Package
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Package {module_ :: Target
module_ = Target
mdl, package :: PackageName
package = PackageName
pkg}

toMap :: [Package] -> Map.Map Target.Target PackageName.PackageName
toMap :: [Package] -> Map Target PackageName
toMap = (PackageName -> PackageName -> PackageName)
-> [(Target, PackageName)] -> Map Target PackageName
forall k a. Ord k => (a -> a -> a) -> [(k, a)] -> Map k a
Map.fromListWith ((PackageName -> PackageName)
-> PackageName -> PackageName -> PackageName
forall a b. a -> b -> a
const PackageName -> PackageName
forall a. a -> a
id) ([(Target, PackageName)] -> Map Target PackageName)
-> ([Package] -> [(Target, PackageName)])
-> [Package]
-> Map Target PackageName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Package -> (Target, PackageName))
-> [Package] -> [(Target, PackageName)]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\Package
x -> (Package -> Target
module_ Package
x, Package -> PackageName
package Package
x))