module CabalBounds.Dump
   ( dump
   ) where

import Distribution.PackageDescription (GenericPackageDescription)
import qualified Data.HashMap.Strict as HM
import Data.List (foldl')
import Data.Maybe (fromMaybe)
import qualified CabalLenses as CL
import CabalBounds.Dependencies (Dependencies(..), allDependency, filterDependency)
import CabalBounds.Types
import Control.Lens


dump :: Dependencies -> [GenericPackageDescription] -> Libraries
dump :: Dependencies -> [GenericPackageDescription] -> Libraries
dump Dependencies
deps [GenericPackageDescription]
pkgDescrps = HashMap LibName LibVersion -> Libraries
forall k v. HashMap k v -> [(k, v)]
HM.toList (HashMap LibName LibVersion -> Libraries)
-> HashMap LibName LibVersion -> Libraries
forall a b. (a -> b) -> a -> b
$ (HashMap LibName LibVersion
 -> GenericPackageDescription -> HashMap LibName LibVersion)
-> HashMap LibName LibVersion
-> [GenericPackageDescription]
-> HashMap LibName LibVersion
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' HashMap LibName LibVersion
-> GenericPackageDescription -> HashMap LibName LibVersion
addLibsFromPkgDescrp HashMap LibName LibVersion
forall k v. HashMap k v
HM.empty [GenericPackageDescription]
pkgDescrps
   where
      addLibsFromPkgDescrp :: HashMap LibName LibVersion
-> GenericPackageDescription -> HashMap LibName LibVersion
addLibsFromPkgDescrp HashMap LibName LibVersion
libs GenericPackageDescription
pkgDescrp =
         (HashMap LibName LibVersion
 -> Dependency -> HashMap LibName LibVersion)
-> HashMap LibName LibVersion
-> [Dependency]
-> HashMap LibName LibVersion
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' HashMap LibName LibVersion
-> Dependency -> HashMap LibName LibVersion
addLibFromDep HashMap LibName LibVersion
libs (GenericPackageDescription
pkgDescrp GenericPackageDescription
-> Getting (Endo [Dependency]) GenericPackageDescription Dependency
-> [Dependency]
forall s a. s -> Getting (Endo [a]) s a -> [a]
^.. Getting (Endo [Dependency]) GenericPackageDescription Dependency
Traversal' GenericPackageDescription Dependency
allDependency Getting (Endo [Dependency]) GenericPackageDescription Dependency
-> ((Dependency -> Const (Endo [Dependency]) Dependency)
    -> Dependency -> Const (Endo [Dependency]) Dependency)
-> Getting (Endo [Dependency]) GenericPackageDescription Dependency
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Dependency -> Const (Endo [Dependency]) Dependency)
-> Dependency -> Const (Endo [Dependency]) Dependency
filterDep)
         where
            filterDep :: (Dependency -> Const (Endo [Dependency]) Dependency)
-> Dependency -> Const (Endo [Dependency]) Dependency
filterDep = Dependencies -> Traversal' Dependency Dependency
filterDependency Dependencies
deps

      addLibFromDep :: HashMap LibName LibVersion
-> Dependency -> HashMap LibName LibVersion
addLibFromDep HashMap LibName LibVersion
libs Dependency
dep
         | LowerBound
lowerBound_ LowerBound -> LowerBound -> Bool
forall a. Eq a => a -> a -> Bool
/= LowerBound
CL.noLowerBound
         = (LibVersion -> LibVersion -> LibVersion)
-> LibName
-> LibVersion
-> HashMap LibName LibVersion
-> HashMap LibName LibVersion
forall k v.
(Eq k, Hashable k) =>
(v -> v -> v) -> k -> v -> HashMap k v -> HashMap k v
HM.insertWith LibVersion -> LibVersion -> LibVersion
forall a. Ord a => a -> a -> a
min LibName
pkgName_ LibVersion
versionBranch_ HashMap LibName LibVersion
libs

         | Bool
otherwise
         = HashMap LibName LibVersion
libs
         where
            pkgName_ :: Unwrapped PackageName
pkgName_       = Dependency
dep Dependency
-> Getting
     (Unwrapped PackageName) Dependency (Unwrapped PackageName)
-> Unwrapped PackageName
forall s a. s -> Getting a s a -> a
^. (PackageName -> Const (Unwrapped PackageName) PackageName)
-> Dependency -> Const (Unwrapped PackageName) Dependency
Lens' Dependency PackageName
CL.packageName ((PackageName -> Const (Unwrapped PackageName) PackageName)
 -> Dependency -> Const (Unwrapped PackageName) Dependency)
-> ((Unwrapped PackageName
     -> Const (Unwrapped PackageName) (Unwrapped PackageName))
    -> PackageName -> Const (Unwrapped PackageName) PackageName)
-> Getting
     (Unwrapped PackageName) Dependency (Unwrapped PackageName)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Unwrapped PackageName
 -> Const (Unwrapped PackageName) (Unwrapped PackageName))
-> PackageName -> Const (Unwrapped PackageName) PackageName
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
Iso
  PackageName
  PackageName
  (Unwrapped PackageName)
  (Unwrapped PackageName)
_Wrapped
            versionBranch_ :: LibVersion
versionBranch_ = LowerBound
lowerBound_ LowerBound
-> Getting LibVersion LowerBound LibVersion -> LibVersion
forall s a. s -> Getting a s a -> a
^. (Version -> Const LibVersion Version)
-> LowerBound -> Const LibVersion LowerBound
Lens' LowerBound Version
CL.version ((Version -> Const LibVersion Version)
 -> LowerBound -> Const LibVersion LowerBound)
-> ((LibVersion -> Const LibVersion LibVersion)
    -> Version -> Const LibVersion Version)
-> Getting LibVersion LowerBound LibVersion
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (LibVersion -> Const LibVersion LibVersion)
-> Version -> Const LibVersion Version
Iso' Version LibVersion
CL.versionBranchL
            lowerBound_ :: LowerBound
lowerBound_    = LowerBound -> Maybe LowerBound -> LowerBound
forall a. a -> Maybe a -> a
fromMaybe LowerBound
CL.noLowerBound (Dependency
dep Dependency
-> Getting (First LowerBound) Dependency LowerBound
-> Maybe LowerBound
forall s a. s -> Getting (First a) s a -> Maybe a
^? (VersionRange -> Const (First LowerBound) VersionRange)
-> Dependency -> Const (First LowerBound) Dependency
Lens' Dependency VersionRange
CL.versionRange ((VersionRange -> Const (First LowerBound) VersionRange)
 -> Dependency -> Const (First LowerBound) Dependency)
-> ((LowerBound -> Const (First LowerBound) LowerBound)
    -> VersionRange -> Const (First LowerBound) VersionRange)
-> Getting (First LowerBound) Dependency LowerBound
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([VersionInterval] -> Const (First LowerBound) [VersionInterval])
-> VersionRange -> Const (First LowerBound) VersionRange
Iso' VersionRange [VersionInterval]
CL.intervals (([VersionInterval] -> Const (First LowerBound) [VersionInterval])
 -> VersionRange -> Const (First LowerBound) VersionRange)
-> ((LowerBound -> Const (First LowerBound) LowerBound)
    -> [VersionInterval] -> Const (First LowerBound) [VersionInterval])
-> (LowerBound -> Const (First LowerBound) LowerBound)
-> VersionRange
-> Const (First LowerBound) VersionRange
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (VersionInterval -> Const (First LowerBound) VersionInterval)
-> [VersionInterval] -> Const (First LowerBound) [VersionInterval]
forall s a. Cons s s a a => Traversal' s a
Traversal' [VersionInterval] VersionInterval
_head ((VersionInterval -> Const (First LowerBound) VersionInterval)
 -> [VersionInterval] -> Const (First LowerBound) [VersionInterval])
-> ((LowerBound -> Const (First LowerBound) LowerBound)
    -> VersionInterval -> Const (First LowerBound) VersionInterval)
-> (LowerBound -> Const (First LowerBound) LowerBound)
-> [VersionInterval]
-> Const (First LowerBound) [VersionInterval]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (LowerBound -> Const (First LowerBound) LowerBound)
-> VersionInterval -> Const (First LowerBound) VersionInterval
Lens' VersionInterval LowerBound
CL.lowerBound)