-- Takes a reversed log file on the standard input and outputs an RSS feed.

module Main (main) where

import Data.List		( nubBy )
import Data.Version		( showVersion )
import Distribution.Package	( PackageIdentifier(..) )
import Distribution.PackageDescription
				( PackageDescription(..), packageDescription )
import Distribution.Text	( display )
import Network.URI		( URI(..), URIAuth(..), uriToString )
import System.Exit		( exitFailure )
import System.IO		( stderr, hPutStrLn )
import System.Locale		( defaultTimeLocale )
import System.Time		( CalendarTime, getClockTime,
				  toCalendarTime, calendarTimeToString )
import System.Time.Parse	( parseCalendarTime )
import Text.RSS			( RSS(..), ChannelElem(..), ItemElem(..),
				  rssToXML, showXML )

import Locations		( recentAdditionsURL )
import Util			( packageURL, readPackageId,
				  loadPackageDescription )

data Upload p = Upload CalendarTime String p

main :: IO ()
main = do
	input <- getContents
	time <- getClockTime
	cal_time <- toCalendarTime time
	case mapM parseLine $ take 20 $ nubBy samepkgId $
		map words $ lines input of
	    Nothing -> do
		hPutStrLn stderr "Parse error"
		exitFailure
	    Just records -> do
		pkg_records <- mapM getPackage records
		putStr $ showXML $ rssToXML $ RSS
			"Recent additions"
			(hackageURI recentAdditionsURL)
			desc
			(channel cal_time)
			(map releaseItem pkg_records)
  where samepkgId xs ys = drop 7 xs == drop 7 ys
	desc = "The 20 most recent additions to HackageDB, the Haskell package database."

getPackage :: Upload PackageIdentifier -> IO (Upload PackageDescription)
getPackage (Upload time user pkgId) = do
	pkg <- loadPackageDescription pkgId
	return (Upload time user (packageDescription pkg))

hackageURI :: String -> URI
hackageURI rel =
	URI "http:" (Just (URIAuth "" "hackage.haskell.org" "")) rel "" ""

parseLine :: [String] -> Maybe (Upload PackageIdentifier)
parseLine wds = do
	[day, mon, dayno, time, tz, year, user, pkg, vers] <- return wds
	ct <- parseCalendarTime defaultTimeLocale "%c" $
		unwords [day, mon, dayno, time, tz, year]
	pkgId <- readPackageId (pkg ++ "-" ++ vers)
	return (Upload ct user pkgId)

channel :: CalendarTime -> [ChannelElem]
channel now =
	[ Language "en"
	, ManagingEditor email
	, WebMaster email
	, ChannelPubDate now
	, LastBuildDate	now
	, Generator "rss-feed"
	]
  where email = "Ross Paterson <ross@soi.city.ac.uk>"

releaseItem :: Upload PackageDescription -> [ItemElem]
releaseItem (Upload ct user pkg) =
	[ Title title
	, Link uri
	, Guid True (uriToString id uri "")
	, PubDate ct
	, Description desc
	]
  where uri = hackageURI (packageURL pkgId)
	pkgId = package pkg
	title = display (pkgName pkgId) ++ " " ++ showVersion (pkgVersion pkgId)
	desc = "<i>Added by " ++ user ++ ", " ++ calendarTimeToString ct ++ ".</i>" ++
		if null (synopsis pkg) then "" else "<p>" ++ synopsis pkg
