module Hcompta.Lib.Map.Strict where

import qualified Data.Foldable as Foldable
import           Data.Map.Strict (Map)
import qualified Data.Map.Strict as Data.Map

import           Hcompta.Lib.Interval (Interval)
import qualified Hcompta.Lib.Interval as Interval
import qualified Hcompta.Lib.Interval.Sieve as Interval.Sieve

-- * Slice

-- | Return an 'Interval' spanning over all the keys of the given 'Map'.
interval :: Ord k => Map k x -> Maybe (Interval k)
interval m | Data.Map.null m = Nothing
interval m =
	(Interval.<=..<=)
	 (fst $ Data.Map.findMin m)
	 (fst $ Data.Map.findMax m)

-- | Return non-'Data.Map.null' sub-'Map's of the given 'Map'
--   sliced according to the given 'Interval.Sieve.Sieve'.
slice
 :: Ord k
 => Interval.Sieve.Sieve k
 -> Map k x -> [Map k x]
slice (Interval.Sieve.Sieve is) m =
	Foldable.foldr
	 (\i ->
		let l = Interval.low  i in
		let h = Interval.high i in
		let (_lt_l, eq_l, gt_l) = Data.Map.splitLookup (Interval.limit l) m in
		let (lt_h, eq_h, _gt_h) = Data.Map.splitLookup (Interval.limit h) gt_l in
		case
			(case Interval.adherence l of
			 Interval.In  -> maybe id (Data.Map.insert (Interval.limit l)) eq_l
			 Interval.Out -> id) $
			(case Interval.adherence h of
			 Interval.In  -> maybe id (Data.Map.insert (Interval.limit h)) eq_h
			 Interval.Out -> id) $
			lt_h of
		 s | Data.Map.null s -> id
		 s -> (:) s
	 ) [] is