{-# LANGUAGE QuasiQuotes, TemplateHaskell, Rank2Types, TypeFamilies, FlexibleInstances, FlexibleContexts, UndecidableInstances, MultiParamTypeClasses #-}

module Data.TrieMap.MultiRec.IMap () where

import Data.TrieMap.MultiRec.Class
import Data.TrieMap.MultiRec.Sized
-- import Data.TrieMap.MultiRec.KeyFam
-- import Data.TrieMap.MultiRec.TT
-- import Data.TrieMap.Rep.TT
-- import Data.TrieMap.Rep
import Data.TrieMap.TrieKey

import Control.Applicative
import Control.Arrow

import Generics.MultiRec

newtype IMap phi xi r ix a = IMap (HTrieMap phi r xi a)
type instance HTrieMapT phi (I xi) = IMap phi xi
-- type instance TTrieMap phi (I xi r) = TTrieMapH phi (I xi) r

-- type instance RepH (IMap phi xi r ix) = RepH (TTrieMap phi r xi)
-- type instance Rep (IMap phi xi r ix a) = RepH (IMap phi xi r ix) (Rep a)
-- 
-- -- $(genRepH [d|
--   instance ReprH (TTrieMap phi r xi) => ReprH (IMap phi xi r ix) where
-- 	toRepH (IMap m) = toRepH m
-- 	fromRepH = IMap . fromRepH |] )

instance (El phi xi) => HTrieKeyT phi (I xi) (IMap phi xi) where
	emptyH _ = IMap (empty0 proof)
	nullH _ (IMap m) = null0 proof m
	sizeH _ s (IMap m) = size0 proof s m
	lookupH _ (I k) (IMap m) = lookup0 proof k m
	lookupIxH _ s (I k) (IMap m) = onKey I (lookupIx0 proof s k m)
	assocAtH _ s i (IMap m) = onKey I (assocAt0 proof s i m)
-- 	updateAtH _ s r f i (IMap m) = IMap (updateAtH proof s r (\ i' -> f i' . I) i m)
	alterH _ s f (I k) (IMap m) = IMap (alter0 proof s f k m)
	alterLookupH _ s f (I k) (IMap m) = IMap <$> alterLookup0 proof s f k m
	traverseWithKeyH _ s f (IMap m) = IMap <$> traverseWithKey0 proof s (f . I) m
	foldWithKeyH _ f (IMap m) = foldWithKey0 proof (f . I) m
	foldlWithKeyH _ f (IMap m) = foldlWithKey0 proof (f . I) m
	mapEitherH _ s1 s2 f (IMap m) = (IMap *** IMap) (mapEither0 proof s1 s2 (f . I) m)
	splitLookupH pf s f (I k) (IMap m) = IMap `sides` splitLookup0 proof s (f) k m
	unionH pf s f (IMap m1) (IMap m2) = IMap (union0 proof s (f . I) m1 m2)
	isectH pf s f (IMap m1) (IMap m2) = IMap (isect0 proof s (f . I) m1 m2)
	diffH pf s f (IMap m1) (IMap m2) = IMap (diff0 proof s (f . I) m1 m2)
	extractH pf s f (IMap m) = fmap IMap <$> extract0 proof s (f . I) m
-- 	extractMinH pf s f (IMap m) = second IMap <$> extractMinH proof s (f . I) m
-- 	extractMaxH pf s f (IMap m) = second IMap <$> extractMaxH proof s (f . I) m
-- 	alterMinH pf s f (IMap m) = IMap <$> alterMinH proof s (f . I) m
-- 	alterMaxH pf s f (IMap m) = IMap <$> alterMaxH proof s (f . I) m
	isSubmapH pf (<=) (IMap m1) (IMap m2) = isSubmap0 proof (<=) m1 m2 
	fromListH _ s f xs = IMap (fromList0 proof s (f . I) [(k, a) | (I k, a) <- xs])
	fromAscListH _ s f xs = IMap (fromAscList0 proof s (f . I) [(k, a) | (I k, a) <- xs])
	fromDistAscListH _ s xs = IMap (fromDistAscList0 proof s [(k, a) | (I k, a) <- xs])