{-# LANGUAGE UndecidableInstances #-}
module Hackage.Security.TUF.Snapshot (
    Snapshot(..)
  ) where
import Control.Monad.Except
import Control.Monad.Reader
import Hackage.Security.JSON
import Hackage.Security.TUF.Header
import Hackage.Security.TUF.FileInfo
import Hackage.Security.TUF.FileMap
import Hackage.Security.TUF.Layout.Repo
import Hackage.Security.TUF.Signed
import qualified Hackage.Security.TUF.FileMap as FileMap
data Snapshot = Snapshot {
    snapshotVersion :: FileVersion
  , snapshotExpires :: FileExpires
    
    
    
    
    
  , snapshotInfoRoot :: FileInfo
    
  , snapshotInfoMirrors :: FileInfo
    
  , snapshotInfoTarGz :: FileInfo
    
    
    
  , snapshotInfoTar :: Maybe FileInfo
  }
instance HasHeader Snapshot where
  fileVersion f x = (\y -> x { snapshotVersion = y }) <$> f (snapshotVersion x)
  fileExpires f x = (\y -> x { snapshotExpires = y }) <$> f (snapshotExpires x)
instance MonadReader RepoLayout m => ToJSON m Snapshot where
  toJSON Snapshot{..} = do
      repoLayout <- ask
      mkObject [
          ("_type"   , return $ JSString "Snapshot")
        , ("version" , toJSON snapshotVersion)
        , ("expires" , toJSON snapshotExpires)
        , ("meta"    , toJSON (snapshotMeta repoLayout))
        ]
    where
      snapshotMeta repoLayout = FileMap.fromList $ [
          (pathRoot       repoLayout , snapshotInfoRoot)
        , (pathMirrors    repoLayout , snapshotInfoMirrors)
        , (pathIndexTarGz repoLayout , snapshotInfoTarGz)
        ] ++
        [ (pathIndexTar   repoLayout , infoTar) | Just infoTar <- [snapshotInfoTar] ]
instance ( MonadReader RepoLayout m
         , MonadError DeserializationError m
         , ReportSchemaErrors m
         ) => FromJSON m Snapshot where
  fromJSON enc = do
    verifyType enc "Snapshot"
    repoLayout          <- ask
    snapshotVersion     <- fromJSField enc "version"
    snapshotExpires     <- fromJSField enc "expires"
    snapshotMeta        <- fromJSField enc "meta"
    snapshotInfoRoot    <- FileMap.lookupM snapshotMeta (pathRoot       repoLayout)
    snapshotInfoMirrors <- FileMap.lookupM snapshotMeta (pathMirrors    repoLayout)
    snapshotInfoTarGz   <- FileMap.lookupM snapshotMeta (pathIndexTarGz repoLayout)
    let snapshotInfoTar = FileMap.lookup (pathIndexTar repoLayout) snapshotMeta
    return Snapshot{..}
instance (MonadKeys m, MonadReader RepoLayout m) => FromJSON m (Signed Snapshot) where
  fromJSON = signedFromJSON
pathRoot, pathMirrors, pathIndexTarGz, pathIndexTar :: RepoLayout -> TargetPath
pathRoot       = TargetPathRepo . repoLayoutRoot
pathMirrors    = TargetPathRepo . repoLayoutMirrors
pathIndexTarGz = TargetPathRepo . repoLayoutIndexTarGz
pathIndexTar   = TargetPathRepo . repoLayoutIndexTar