recentPackagesFeature :: ServerEnv
                      -> UserFeature
                      -> CoreFeature
                      -> PackageContentsFeature
                      -> AsyncCache (Response, Response, Response, Response)
                      -> (RecentPackagesFeature, IO (Response, Response, Response, Response))

recentPackagesFeature env
                      UserFeature{..}
                      CoreFeature{..}
                      PackageContentsFeature{packageChangeLog}
                      cacheRecent
  = (RecentPackagesFeature{..}, updateRecentCache)
  where
    recentPackagesFeatureInterface = (emptyHackageFeature "recentPackages") {
        featureResources = map ($ recentPackagesResource) [recentPackages, recentRevisions]
      , featureState     = []
      , featureCaches    = [
            CacheComponent {
              cacheDesc       = "recents packages and revisions page (html, rss, html, rss)",
              getCacheMemSize = memSize <$> readAsyncCache cacheRecent
            }
          ]
      , featurePostInit = syncAsyncCache cacheRecent
      }

    recentPackagesResource = RecentPackagesResource {
        recentPackages = (extendResourcePath "/recent.:format" (corePackagesPage coreResource)) {
            resourceGet = [
                ("html", const $ liftM (\(x,_,_,_) -> x) $ readAsyncCache cacheRecent)
              , ("rss",  const $ liftM (\(_,x,_,_) -> x) $ readAsyncCache cacheRecent)
              ]
          },
        recentRevisions = (extendResourcePath "/recent/revisions.:format" (corePackagesPage coreResource)) {
            resourceGet = [
                ("html", const $ liftM (\(_,_,x,_) -> x) $ readAsyncCache cacheRecent)
              , ("rss",  const $ liftM (\(_,_,_,x) -> x) $ readAsyncCache cacheRecent)
              ]
          }
      }

    packageRender pkg = do
      users <- queryGetUserDb
      changeLog <- packageChangeLog pkg
      let showChangeLogLink = case changeLog of Right _ -> True ; _ -> False
      doPackageRender users pkg showChangeLogLink

    updateRecentCache = do
        -- TODO: move the html version to the HTML feature
        pkgIndex <- queryGetPackageIndex
        users <- queryGetUserDb
        now   <- getCurrentTime
        let recentChanges = sortBy (flip $ comparing pkgOriginalUploadTime)
                            (PackageIndex.allPackages pkgIndex)
            xmlRepresentation = toResponse $ Resource.XHtml $ Pages.recentPage users recentChanges
            rssRepresentation = toResponse $ Pages.recentFeed users (serverBaseURI env) now recentChanges

            recentRevisions = sortBy (flip $ comparing revisionTime) .
                              filter isRevised $ (PackageIndex.allPackages pkgIndex)
            revisionTime pkgInfo = pkgLatestUploadTime pkgInfo
            isRevised pkgInfo = pkgNumRevisions pkgInfo > 1
            xmlRevisions = toResponse $ Resource.XHtml $ Pages.revisionsPage users recentRevisions
            rssRevisions = toResponse $ Pages.recentRevisionsFeed users (serverBaseURI env) now recentRevisions

        return (xmlRepresentation, rssRepresentation, xmlRevisions, rssRevisions)


{-
data SimpleCondTree = SimpleCondNode [Dependency] [(Condition ConfVar, SimpleCondTree, SimpleCondTree)]
                    | SimpleCondLeaf
    deriving (Show, Eq)

doMakeCondTree :: GenericPackageDescription -> [(String, SimpleCondTree)]
doMakeCondTree desc = map (\lib -> ("library", makeCondTree lib)) (maybeToList $ condLibrary desc)
                   ++ map (\(exec, tree) -> (exec, makeCondTree tree)) (condExecutables desc)
  where
    makeCondTree (CondNode _ deps comps) = case deps of
        [] -> SimpleCondLeaf
        _  -> SimpleCondNode deps $ map makeCondComponents comps
    makeCondComponents (cond, tree, mtree) = (cond, makeCondTree tree, maybe SimpleCondLeaf makeCondTree mtree)
-}
recentPackagesFeature :: ServerEnv
                      -> UserFeature
                      -> CoreFeature
                      -> PackageContentsFeature
                      -> AsyncCache (Response, Response, Response, Response)
                      -> (RecentPackagesFeature, IO (Response, Response, Response, Response))
recentPackagesFeature env
                      UserFeature{..}
                      CoreFeature{..}
                      PackageContentsFeature{packageChangeLog}
                      cacheRecent
  = (RecentPackagesFeature{..}, updateRecentCache)
  where
    recentPackagesFeatureInterface = (emptyHackageFeature "recentPackages") {
        featureResources = map ($ recentPackagesResource) [recentPackages, recentRevisions]
      , featureState     = []
      , featureCaches    = [
            CacheComponent {
              cacheDesc       = "recents packages and revisions page (html, rss, html, rss)",
              getCacheMemSize = memSize <$> readAsyncCache cacheRecent
            }
          ]
      , featurePostInit = syncAsyncCache cacheRecent
      }

    recentPackagesResource = RecentPackagesResource {
        recentPackages = (extendResourcePath "/recent.:format" (corePackagesPage coreResource)) {
            resourceGet = [
                ("html", const $ liftM (\(x,_,_,_) -> x) $ readAsyncCache cacheRecent)
              , ("rss",  const $ liftM (\(_,x,_,_) -> x) $ readAsyncCache cacheRecent)
              ]
          },
        recentRevisions = (extendResourcePath "/recent/revisions.:format" (corePackagesPage coreResource)) {
            resourceGet = [
                ("html", const $ liftM (\(_,_,x,_) -> x) $ readAsyncCache cacheRecent)
              , ("rss",  const $ liftM (\(_,_,_,x) -> x) $ readAsyncCache cacheRecent)
              ]
          }
      }

    packageRender pkg = do
      users <- queryGetUserDb
      changeLog <- packageChangeLog pkg
      let showChangeLogLink = case changeLog of Right _ -> True ; _ -> False
      doPackageRender users pkg showChangeLogLink

    updateRecentCache = do
        -- TODO: move the html version to the HTML feature
        pkgIndex <- queryGetPackageIndex
        users <- queryGetUserDb
        now   <- getCurrentTime
        let recentChanges = sortBy (flip $ comparing pkgOriginalUploadTime)
                            (PackageIndex.allPackages pkgIndex)
            xmlRepresentation = toResponse $ Resource.XHtml $ Pages.recentPage users recentChanges
            rssRepresentation = toResponse $ Pages.recentFeed users (serverBaseURI env) now recentChanges

            recentRevisions = sortBy (flip $ comparing revisionTime) .
                              filter isRevised $ (PackageIndex.allPackages pkgIndex)
            revisionTime pkgInfo = pkgLatestUploadTime pkgInfo
            isRevised pkgInfo = pkgNumRevisions pkgInfo > 1
            xmlRevisions = toResponse $ Resource.XHtml $ Pages.revisionsPage users recentRevisions
            rssRevisions = toResponse $ Pages.recentRevisionsFeed users (serverBaseURI env) now recentRevisions

        return (xmlRepresentation, rssRepresentation, xmlRevisions, rssRevisions)


{-
data SimpleCondTree = SimpleCondNode [Dependency] [(Condition ConfVar, SimpleCondTree, SimpleCondTree)]
                    | SimpleCondLeaf
    deriving (Show, Eq)

doMakeCondTree :: GenericPackageDescription -> [(String, SimpleCondTree)]
doMakeCondTree desc = map (\lib -> ("library", makeCondTree lib)) (maybeToList $ condLibrary desc)
                   ++ map (\(exec, tree) -> (exec, makeCondTree tree)) (condExecutables desc)
  where
    makeCondTree (CondNode _ deps comps) = case deps of
        [] -> SimpleCondLeaf
        _  -> SimpleCondNode deps $ map makeCondComponents comps
    makeCondComponents (cond, tree, mtree) = (cond, makeCondTree tree, maybe SimpleCondLeaf makeCondTree mtree)
-}
recentPackagesFeature env
                      UserFeature{..}
                      CoreFeature{..}
                      PackageContentsFeature{packageChangeLog}
                      cacheRecent
  = (RecentPackagesFeature{..}, updateRecentCache)
  where
    recentPackagesFeatureInterface = (emptyHackageFeature "recentPackages") {
        featureResources = map ($ recentPackagesResource) [recentPackages, recentRevisions]
      , featureState     = []
      , featureCaches    = [
            CacheComponent {
              cacheDesc       = "recents packages and revisions page (html, rss, html, rss)",
              getCacheMemSize = memSize <$> readAsyncCache cacheRecent
            }
          ]
      , featurePostInit = syncAsyncCache cacheRecent
      }

    recentPackagesResource = RecentPackagesResource {
        recentPackages = (extendResourcePath "/recent.:format" (corePackagesPage coreResource)) {
            resourceGet = [
                ("html", const $ liftM (\(x,_,_,_) -> x) $ readAsyncCache cacheRecent)
              , ("rss",  const $ liftM (\(_,x,_,_) -> x) $ readAsyncCache cacheRecent)
              ]
          },
        recentRevisions = (extendResourcePath "/recent/revisions.:format" (corePackagesPage coreResource)) {
            resourceGet = [
                ("html", const $ liftM (\(_,_,x,_) -> x) $ readAsyncCache cacheRecent)
              , ("rss",  const $ liftM (\(_,_,_,x) -> x) $ readAsyncCache cacheRecent)
              ]
          }
      }

    packageRender pkg = do
      users <- queryGetUserDb
      changeLog <- packageChangeLog pkg
      let showChangeLogLink = case changeLog of Right _ -> True ; _ -> False
      doPackageRender users pkg showChangeLogLink

    updateRecentCache = do
        -- TODO: move the html version to the HTML feature
        pkgIndex <- queryGetPackageIndex
        users <- queryGetUserDb
        now   <- getCurrentTime
        let recentChanges = sortBy (flip $ comparing pkgOriginalUploadTime)
                            (PackageIndex.allPackages pkgIndex)
            xmlRepresentation = toResponse $ Resource.XHtml $ Pages.recentPage users recentChanges
            rssRepresentation = toResponse $ Pages.recentFeed users (serverBaseURI env) now recentChanges

            recentRevisions = sortBy (flip $ comparing revisionTime) .
                              filter isRevised $ (PackageIndex.allPackages pkgIndex)
            revisionTime pkgInfo = pkgLatestUploadTime pkgInfo
            isRevised pkgInfo = pkgNumRevisions pkgInfo > 1
            xmlRevisions = toResponse $ Resource.XHtml $ Pages.revisionsPage users recentRevisions
            rssRevisions = toResponse $ Pages.recentRevisionsFeed users (serverBaseURI env) now recentRevisions

        return (xmlRepresentation, rssRepresentation, xmlRevisions, rssRevisions)


{-
data SimpleCondTree = SimpleCondNode [Dependency] [(Condition ConfVar, SimpleCondTree, SimpleCondTree)]
                    | SimpleCondLeaf
    deriving (Show, Eq)

doMakeCondTree :: GenericPackageDescription -> [(String, SimpleCondTree)]
doMakeCondTree desc = map (\lib -> ("library", makeCondTree lib)) (maybeToList $ condLibrary desc)
                   ++ map (\(exec, tree) -> (exec, makeCondTree tree)) (condExecutables desc)
  where
    makeCondTree (CondNode _ deps comps) = case deps of
        [] -> SimpleCondLeaf
        _  -> SimpleCondNode deps $ map makeCondComponents comps
    makeCondComponents (cond, tree, mtree) = (cond, makeCondTree tree, maybe SimpleCondLeaf makeCondTree mtree)
-}