{-# LANGUAGE UndecidableInstances #-}
module Hackage.Security.TUF.Mirrors (
    
    Mirrors(..)
  , Mirror(..)
  , MirrorContent(..)
    
  , MirrorDescription
  , describeMirror
  ) where
import Control.Monad.Except
import Network.URI
import Hackage.Security.JSON
import Hackage.Security.TUF.Header
import Hackage.Security.TUF.Signed
data Mirrors = Mirrors {
    mirrorsVersion :: FileVersion
  , mirrorsExpires :: FileExpires
  , mirrorsMirrors :: [Mirror]
  }
data Mirror = Mirror {
    mirrorUrlBase :: URI
  , mirrorContent :: MirrorContent
  }
  deriving Show
data MirrorContent =
    MirrorFull
  deriving Show
instance HasHeader Mirrors where
  fileVersion f x = (\y -> x { mirrorsVersion = y }) <$> f (mirrorsVersion x)
  fileExpires f x = (\y -> x { mirrorsExpires = y }) <$> f (mirrorsExpires x)
type MirrorDescription = String
describeMirror :: Mirror -> MirrorDescription
describeMirror = show . mirrorUrlBase
instance Monad m => ToJSON m Mirror where
  toJSON Mirror{..} = mkObject $ concat [
      [ ("urlbase", toJSON mirrorUrlBase) ]
    , case mirrorContent of
        MirrorFull -> []
    ]
instance Monad m => ToJSON m Mirrors where
  toJSON Mirrors{..} = mkObject [
      ("_type"   , return $ JSString "Mirrorlist")
    , ("version" , toJSON mirrorsVersion)
    , ("expires" , toJSON mirrorsExpires)
    , ("mirrors" , toJSON mirrorsMirrors)
    ]
instance ReportSchemaErrors m => FromJSON m Mirror where
  fromJSON enc = do
    mirrorUrlBase <- fromJSField enc "urlbase"
    let mirrorContent = MirrorFull
    return Mirror{..}
instance ( MonadError DeserializationError m
         , ReportSchemaErrors m
         ) => FromJSON m Mirrors where
  fromJSON enc = do
    verifyType enc "Mirrorlist"
    mirrorsVersion <- fromJSField enc "version"
    mirrorsExpires <- fromJSField enc "expires"
    mirrorsMirrors <- fromJSField enc "mirrors"
    return Mirrors{..}
instance MonadKeys m => FromJSON m (Signed Mirrors) where
  fromJSON = signedFromJSON