module IdeSession.Strict.IntervalMap (
    StrictIntervalMap
  , dominators
  , fromList
  , toList
  , empty
  , insert
    
  , Interval(..)
  ) where
import Data.IntervalMap.FingerTree (Interval(..), IntervalMap)
import qualified Data.IntervalMap.FingerTree as IntervalMap
import Text.Show.Pretty
data StrictIntervalMap v a = StrictIntervalMap {
    toLazyIntervalMap :: !(IntervalMap v a)
  , maxInterval       :: !(Maybe (Interval v))
  }
instance (Ord v, Show v, Show a) => Show (StrictIntervalMap v a) where
  show m = "fromList " ++ show (toList m)
instance (Ord v, PrettyVal v, PrettyVal a) => PrettyVal (StrictIntervalMap v a) where
  prettyVal m = Con "fromList" [prettyVal . map flattenIntervals . toList $ m]
    where
      flattenIntervals :: (Interval v, a) -> ((v, v), a)
      flattenIntervals (Interval lo hi, a) = ((lo, hi), a)
unionInterval :: Ord v => Interval v -> Maybe (Interval v) -> Maybe (Interval v)
unionInterval i@(Interval low high) Nothing =
  low `seq` high `seq` Just i
unionInterval (Interval low1 high1) (Just (Interval low2 high2)) =
  let low  = min low1  low2
      high = max high1 high2
  in low `seq` high `seq` Just (Interval low high)
dominators :: Ord v => Interval v -> StrictIntervalMap v a -> [(Interval v, a)]
dominators i = IntervalMap.dominators i . toLazyIntervalMap
empty :: Ord v => StrictIntervalMap v a
empty = StrictIntervalMap IntervalMap.empty Nothing
insert :: Ord v => Interval v -> a -> StrictIntervalMap v a -> StrictIntervalMap v a
insert i a m =
  a `seq` StrictIntervalMap {
      toLazyIntervalMap = IntervalMap.insert i a $ toLazyIntervalMap m
    , maxInterval       = unionInterval i        $ maxInterval m
    }
fromList :: Ord v => [(Interval v, a)] -> StrictIntervalMap v a
fromList = foldr (\(i, a) m -> insert i a m) empty
toList :: Ord v => StrictIntervalMap v a -> [(Interval v, a)]
toList m = case maxInterval m of
             Nothing -> []
             Just i  -> IntervalMap.intersections i (toLazyIntervalMap m)