module Language.Drasil.Chunk.ConstraintMap (ConstraintCEMap, ConstraintCE,
  constraintMap, physLookup, sfwrLookup
) where

import Control.Lens ((^.))

import Language.Drasil (Constraint, HasUID(..), UID, Constrained(..),
  isPhysC, isSfwrC)
import Language.Drasil.CodeExpr.Development (CodeExpr, constraint)
import qualified Data.Map as Map

-- | Type synonym for 'Constraint CodeExpr'
type ConstraintCE = Constraint CodeExpr

-- | Constraints map. Contains all 'Constraint's.
type ConstraintCEMap = Map.Map UID [ConstraintCE]

-- | Creates a map from 'UID' to 'Constraint's for constrained chunks.
constraintMap :: (HasUID c, Constrained c) => [c] -> ConstraintCEMap
constraintMap :: forall c. (HasUID c, Constrained c) => [c] -> ConstraintCEMap
constraintMap = [(UID, [ConstraintCE])] -> ConstraintCEMap
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(UID, [ConstraintCE])] -> ConstraintCEMap)
-> ([c] -> [(UID, [ConstraintCE])]) -> [c] -> ConstraintCEMap
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (c -> (UID, [ConstraintCE])) -> [c] -> [(UID, [ConstraintCE])]
forall a b. (a -> b) -> [a] -> [b]
map (\c
x -> (c
x c -> Getting UID c UID -> UID
forall s a. s -> Getting a s a -> a
^. Getting UID c UID
forall c. HasUID c => Getter c UID
Getter c UID
uid, (ConstraintE -> ConstraintCE) -> [ConstraintE] -> [ConstraintCE]
forall a b. (a -> b) -> [a] -> [b]
map ConstraintE -> ConstraintCE
constraint ([ConstraintE] -> [ConstraintCE])
-> [ConstraintE] -> [ConstraintCE]
forall a b. (a -> b) -> a -> b
$ c
x c -> Getting [ConstraintE] c [ConstraintE] -> [ConstraintE]
forall s a. s -> Getting a s a -> a
^. Getting [ConstraintE] c [ConstraintE]
forall c. Constrained c => Lens' c [ConstraintE]
Lens' c [ConstraintE]
constraints))

-- | Returns a pair of a chunk and its physical constraints.
physLookup :: HasUID q => ConstraintCEMap -> q -> (q, [ConstraintCE])
physLookup :: forall q. HasUID q => ConstraintCEMap -> q -> (q, [ConstraintCE])
physLookup ConstraintCEMap
m q
q = q
-> ConstraintCEMap
-> ([ConstraintCE] -> [ConstraintCE])
-> (q, [ConstraintCE])
forall q.
HasUID q =>
q
-> ConstraintCEMap
-> ([ConstraintCE] -> [ConstraintCE])
-> (q, [ConstraintCE])
constraintLookup q
q ConstraintCEMap
m ((ConstraintCE -> Bool) -> [ConstraintCE] -> [ConstraintCE]
forall a. (a -> Bool) -> [a] -> [a]
filter ConstraintCE -> Bool
forall e. Constraint e -> Bool
isPhysC)

-- | Returns a pair of a chunk and its software constraints.
sfwrLookup :: HasUID q => ConstraintCEMap -> q -> (q, [ConstraintCE])
sfwrLookup :: forall q. HasUID q => ConstraintCEMap -> q -> (q, [ConstraintCE])
sfwrLookup ConstraintCEMap
m q
q = q
-> ConstraintCEMap
-> ([ConstraintCE] -> [ConstraintCE])
-> (q, [ConstraintCE])
forall q.
HasUID q =>
q
-> ConstraintCEMap
-> ([ConstraintCE] -> [ConstraintCE])
-> (q, [ConstraintCE])
constraintLookup q
q ConstraintCEMap
m ((ConstraintCE -> Bool) -> [ConstraintCE] -> [ConstraintCE]
forall a. (a -> Bool) -> [a] -> [a]
filter ConstraintCE -> Bool
forall e. Constraint e -> Bool
isSfwrC)

-- | Returns a chunk and a filtered list of its constraints.
constraintLookup :: HasUID q => q -> ConstraintCEMap
                      -> ([ConstraintCE] -> [ConstraintCE]) -> (q, [ConstraintCE])
constraintLookup :: forall q.
HasUID q =>
q
-> ConstraintCEMap
-> ([ConstraintCE] -> [ConstraintCE])
-> (q, [ConstraintCE])
constraintLookup q
q ConstraintCEMap
m [ConstraintCE] -> [ConstraintCE]
filt = (q
q, [ConstraintCE]
-> ([ConstraintCE] -> [ConstraintCE])
-> Maybe [ConstraintCE]
-> [ConstraintCE]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] [ConstraintCE] -> [ConstraintCE]
filt (UID -> ConstraintCEMap -> Maybe [ConstraintCE]
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup (q
q q -> Getting UID q UID -> UID
forall s a. s -> Getting a s a -> a
^. Getting UID q UID
forall c. HasUID c => Getter c UID
Getter q UID
uid) ConstraintCEMap
m))