{-# LANGUAGE Trustworthy, Rank2Types, TypeFamilies, FlexibleContexts #-}

module Data.Columbia (module Data.Columbia.CompoundData, module Data.Columbia.CycleDetection, module Data.Columbia.Utils, module Data.Columbia.Integral, module Data.Columbia.Gc, module Data.Columbia.FRecord, module Data.Columbia.WithAddress, module Data.Generics.SYB.WithClass.Basics, module Data.Generics.SYB.WithClass.Context, module Generics.Pointless.Functors, module Control.Monad.IO.Class, module Control.Monad.Reader,
-- ** Idioms
rwProxy, readCompoundData, writeCompoundData, rwKeyProxy, readDataWithCycles, writeDataWithCycles) where

import Data.Map
import Data.Dynamic (Dynamic)
import Data.Columbia.CompoundData
import Data.Columbia.CycleDetection
import Data.Columbia.Utils
import Data.Columbia.Integral
import Data.Columbia.Gc
import Data.Columbia.FRecord
import Data.Columbia.WithAddress
import Data.Columbia.DynamicWithCtx
import Data.Generics.SYB.WithClass.Basics
import Data.Generics.SYB.WithClass.Context
import Data.Word
import Control.Monad.IO.Class
import Control.Monad.Reader
import Generics.Pointless.Functors hiding (Functor,fmap)

rwProxy :: Proxy(PairCtx RWCtx NoCtx)
rwProxy = undefined

-- | Most common idiom of using 'readOneLayer'; reads an entire data structure.
readCompoundData :: forall m d. (Monad m, Data(PairCtx RWCtx NoCtx) d) => ReaderT(SeekableStream m Word8) m d
readCompoundData = fixT rwProxy(withAddresses #. readOneLayer)

-- | Convenient idiom; sells targets repeatedly until the entire data structure has been written.
writeCompoundData :: forall m d. (Monad m, Data(PairCtx RWCtx NoCtx) d)
	=> d -> ReaderT(SeekableWriter m Word8) m ()
writeCompoundData = fixTW rwProxy(writeBackAddresses ##. writeOneLayer)

rwKeyProxy :: Proxy(PairCtx RWCtx(PairCtx KeyCtx NoCtx))
rwKeyProxy = undefined

readDataWithCycles :: forall m d. (MonadFix m, StateM m, StateOf m ~ Map Word32 Dynamic, Data(PairCtx RWCtx(PairCtx KeyCtx NoCtx)) d) => ReaderT(SeekableStream m Word8) m d
readDataWithCycles = fixT rwKeyProxy(withAddresses #. cycleDetect #. readOneLayer)

writeDataWithCycles :: forall m d. (StateM m, StateOf m ~ Map(DynamicWithCtx KeyComparable) Word32, Data(PairCtx RWCtx(PairCtx KeyCtx NoCtx)) d)
	=> d -> ReaderT(SeekableWriter m Word8) m ()
writeDataWithCycles = fixTW rwKeyProxy(writeBackAddresses ##. cycleDetectW ##. writeOneLayer)