module Main where

import Control.Arrow
import Control.Monad (foldM)
import Control.Parallel.Strategies (rnf)
import qualified Data.ByteString.Char8 as B 
import qualified Data.IntMap as M
import Data.List (foldl')
import System.Directory
import System.Environment (getArgs)
import System.IO (stderr, hPutStr)

loadMovie :: String -> IO (Maybe (Int, M.IntMap Int))
loadMovie path = 
    do text <- B.readFile path 
       return $
          case B.lines text of
            []     -> Nothing
            (s:ss) -> 
                let Just (movie, _) = B.readInt s
                in Just (movie, ratings ss)
    where addInt list string = (movie, rating) : list
              where Just (movie, rest) = B.readInt string
                    Just (rating, _)   = B.readInt (B.tail rest) 
          ratings ss = rnf l `seq` M.fromList l
              where l = foldl' addInt [] ss

load :: String -> IO (M.IntMap (M.IntMap Int))
load path =
    do files <- getDirectoryContents path
       case files of 
         [] -> return M.empty
         _  -> foldM addMovie M.empty files
    where addMovie :: M.IntMap (M.IntMap Int) -> String -> IO (M.IntMap (M.IntMap Int))
          addMovie map file =
              if file == "." || file == ".."
              then return map
              else do Just (movie, ratings) <- loadMovie (path ++ "\\" ++  file)
                      hPutStr stderr "."
                      return $ M.insert movie ratings map 

averages path =
    do movies <- load path
       let averages = map (\(movie, ratings) -> (movie, M.fold (\rating (sum, count) -> (sum + rating, count + 1)) (0,0) ratings)) (M.toList movies)
           averages' = map (second (\(sum, length) -> fromIntegral sum / fromIntegral length)) averages
       mapM_ print averages'
                      

main = 
    do args <- getArgs
       averages (args !! 0)