initSecureRepo :: Verbosity
               -> Sec.HTTP.HttpLib
               -> RemoteRepo  -- ^ Secure repo ('remoteRepoSecure' assumed)
               -> Sec.Path Sec.Absolute -- ^ Cache dir
               -> (SecureRepo -> IO a)  -- ^ Callback
               -> IO a
initSecureRepo verbosity httpLib RemoteRepo{..} cachePath = \callback -> do
    requiresBootstrap <- withRepo [] Sec.requiresBootstrap

    mirrors <- if requiresBootstrap
               then do
                   info verbosity $ "Trying to locate mirrors via DNS for " ++
                                    "initial bootstrap of secure " ++
                                    "repository '" ++ show remoteRepoURI ++
                                    "' ..."

                   Sec.DNS.queryBootstrapMirrors verbosity remoteRepoURI
               else pure []

    withRepo mirrors $ \r -> do
      when requiresBootstrap $ Sec.uncheckClientErrors $
        Sec.bootstrap r
          (map Sec.KeyId    remoteRepoRootKeys)
          (Sec.KeyThreshold (fromIntegral remoteRepoKeyThreshold))
      callback $ SecureRepo r
  where
    -- Initialize local or remote repo depending on the URI
    withRepo :: [URI] -> (forall down. Sec.Repository down -> IO a) -> IO a
    withRepo _ callback | uriScheme remoteRepoURI == "file:" = do
      dir <- Sec.makeAbsolute $ Sec.fromFilePath (uriPath remoteRepoURI)
      Sec.Local.withRepository dir
                               cache
                               Sec.hackageRepoLayout
                               Sec.hackageIndexLayout
                               logTUF
                               callback
    withRepo mirrors callback =
      Sec.Remote.withRepository httpLib
                                (remoteRepoURI:mirrors)
                                Sec.Remote.defaultRepoOpts
                                cache
                                Sec.hackageRepoLayout
                                Sec.hackageIndexLayout
                                logTUF
                                callback

    cache :: Sec.Cache
    cache = Sec.Cache {
        cacheRoot   = cachePath
      , cacheLayout = Sec.cabalCacheLayout {
            Sec.cacheLayoutIndexTar   = cacheFn "01-index.tar"
          , Sec.cacheLayoutIndexIdx   = cacheFn "01-index.tar.idx"
          , Sec.cacheLayoutIndexTarGz = cacheFn "01-index.tar.gz"
          }
      }

    cacheFn :: FilePath -> Sec.CachePath
    cacheFn = Sec.rootPath . Sec.fragment

    -- We display any TUF progress only in verbose mode, including any transient
    -- verification errors. If verification fails, then the final exception that
    -- is thrown will of course be shown.
    logTUF :: Sec.LogMessage -> IO ()
    logTUF = info verbosity . Sec.pretty
initSecureRepo :: Verbosity
               -> Sec.HTTP.HttpLib
               -> RemoteRepo  -- ^ Secure repo ('remoteRepoSecure' assumed)
               -> Sec.Path Sec.Absolute -- ^ Cache dir
               -> (SecureRepo -> IO a)  -- ^ Callback
               -> IO a
initSecureRepo verbosity httpLib RemoteRepo{..} cachePath = \callback -> do
    requiresBootstrap <- withRepo [] Sec.requiresBootstrap

    mirrors <- if requiresBootstrap
               then do
                   info verbosity $ "Trying to locate mirrors via DNS for " ++
                                    "initial bootstrap of secure " ++
                                    "repository '" ++ show remoteRepoURI ++
                                    "' ..."

                   Sec.DNS.queryBootstrapMirrors verbosity remoteRepoURI
               else pure []

    withRepo mirrors $ \r -> do
      when requiresBootstrap $ Sec.uncheckClientErrors $
        Sec.bootstrap r
          (map Sec.KeyId    remoteRepoRootKeys)
          (Sec.KeyThreshold (fromIntegral remoteRepoKeyThreshold))
      callback $ SecureRepo r
  where
    -- Initialize local or remote repo depending on the URI
    withRepo :: [URI] -> (forall down. Sec.Repository down -> IO a) -> IO a
    withRepo _ callback | uriScheme remoteRepoURI == "file:" = do
      dir <- Sec.makeAbsolute $ Sec.fromFilePath (uriPath remoteRepoURI)
      Sec.Local.withRepository dir
                               cache
                               Sec.hackageRepoLayout
                               Sec.hackageIndexLayout
                               logTUF
                               callback
    withRepo mirrors callback =
      Sec.Remote.withRepository httpLib
                                (remoteRepoURI:mirrors)
                                Sec.Remote.defaultRepoOpts
                                cache
                                Sec.hackageRepoLayout
                                Sec.hackageIndexLayout
                                logTUF
                                callback

    cache :: Sec.Cache
    cache = Sec.Cache {
        cacheRoot   = cachePath
      , cacheLayout = Sec.cabalCacheLayout {
            Sec.cacheLayoutIndexTar   = cacheFn "01-index.tar"
          , Sec.cacheLayoutIndexIdx   = cacheFn "01-index.tar.idx"
          , Sec.cacheLayoutIndexTarGz = cacheFn "01-index.tar.gz"
          }
      }

    cacheFn :: FilePath -> Sec.CachePath
    cacheFn = Sec.rootPath . Sec.fragment

    -- We display any TUF progress only in verbose mode, including any transient
    -- verification errors. If verification fails, then the final exception that
    -- is thrown will of course be shown.
    logTUF :: Sec.LogMessage -> IO ()
    logTUF = info verbosity . Sec.pretty
initSecureRepo verbosity httpLib RemoteRepo{..} cachePath = \callback -> do
    requiresBootstrap <- withRepo [] Sec.requiresBootstrap

    mirrors <- if requiresBootstrap
               then do
                   info verbosity $ "Trying to locate mirrors via DNS for " ++
                                    "initial bootstrap of secure " ++
                                    "repository '" ++ show remoteRepoURI ++
                                    "' ..."

                   Sec.DNS.queryBootstrapMirrors verbosity remoteRepoURI
               else pure []

    withRepo mirrors $ \r -> do
      when requiresBootstrap $ Sec.uncheckClientErrors $
        Sec.bootstrap r
          (map Sec.KeyId    remoteRepoRootKeys)
          (Sec.KeyThreshold (fromIntegral remoteRepoKeyThreshold))
      callback $ SecureRepo r
  where
    -- Initialize local or remote repo depending on the URI
    withRepo :: [URI] -> (forall down. Sec.Repository down -> IO a) -> IO a
    withRepo _ callback | uriScheme remoteRepoURI == "file:" = do
      dir <- Sec.makeAbsolute $ Sec.fromFilePath (uriPath remoteRepoURI)
      Sec.Local.withRepository dir
                               cache
                               Sec.hackageRepoLayout
                               Sec.hackageIndexLayout
                               logTUF
                               callback
    withRepo mirrors callback =
      Sec.Remote.withRepository httpLib
                                (remoteRepoURI:mirrors)
                                Sec.Remote.defaultRepoOpts
                                cache
                                Sec.hackageRepoLayout
                                Sec.hackageIndexLayout
                                logTUF
                                callback

    cache :: Sec.Cache
    cache = Sec.Cache {
        cacheRoot   = cachePath
      , cacheLayout = Sec.cabalCacheLayout {
            Sec.cacheLayoutIndexTar   = cacheFn "01-index.tar"
          , Sec.cacheLayoutIndexIdx   = cacheFn "01-index.tar.idx"
          , Sec.cacheLayoutIndexTarGz = cacheFn "01-index.tar.gz"
          }
      }

    cacheFn :: FilePath -> Sec.CachePath
    cacheFn = Sec.rootPath . Sec.fragment

    -- We display any TUF progress only in verbose mode, including any transient
    -- verification errors. If verification fails, then the final exception that
    -- is thrown will of course be shown.
    logTUF :: Sec.LogMessage -> IO ()
    logTUF = info verbosity . Sec.pretty