module GraphConstruction (parseData, buildGraph, readDataParallel) where

import Data.Set as Set ( Set, fromList, singleton, union )
import Data.Map as Map ( Map, empty, insert, insertWith, unionWith )
import Data.List.Split ( splitOn )
import Control.Parallel.Strategies( runEval, rpar, rseq )

parseData :: String -> IO (Map.Map String (Set String))
parseData filename = do
    contents <- readFile filename
    return (buildGraph (lines contents) Map.empty)

buildGraph :: [String] -> Map.Map String (Set String) -> Map.Map String (Set String)
buildGraph [] graph = graph
buildGraph (x:xs) graph = buildGraph xs graphWMovies
    where graphWMovies = foldr (\movie g -> Map.insertWith Set.union movie (Set.singleton name) g) graphWActor movies
          graphWActor = Map.insert name (Set.fromList movies) graph -- insert actor keys
          movies = splitOn "," movieStr
          [name, movieStr] = splitOn "\t" x

readDataParallel :: String -> IO (Map.Map String (Set String))
readDataParallel filenamePrefix = runEval $ do
    d1 <- rpar (parseData $ filenamePrefix ++ "1.csv")
    d2 <- rpar (parseData $ filenamePrefix ++ "2.csv")
    d3 <- rpar (parseData $ filenamePrefix ++ "3.csv")
    d4 <- rpar (parseData $ filenamePrefix ++ "4.csv")
    _ <- rseq d1
    _ <- rseq d2
    _ <- rseq d3
    _ <- rseq d4
    m1 <- rpar (Map.unionWith Set.union <$>  d1  <*>  d2)
    m2 <- rpar (Map.unionWith Set.union <$>  d3  <*>  d4)
    _ <- rseq m1
    _ <- rseq m2
    return (Map.unionWith Set.union <$>  m1  <*>  m2)

    --return foldr (\v m -> Map.unionWith (Set.union) <$>  m  <*>  v) d1 [d2, d3, d4]
    --return (Map.unionWith (Set.union) <$>  d1  <*>  d2)