module examples.Concurrent where

import System.Random
import Java.Net (URL)
import Control.Concurrent as C

main2 args = do
    m <- newEmptyMVar
    forkIO do
        m.put 'x'
        m.put 'y' 
        m.put 'z'
    replicateM_ 3 do
        c <- m.take
        print "got: "
        println c  
        
            
example1 = do
    forkIO (replicateM_ 100000 (putChar 'a'))
    replicateM_ 100000 (putChar 'b')

example2 =  do
    s <- getLine
    case s.long of
        Right n -> forkIO (setReminder n) >> example2
        Left _  -> println ("exiting ...")
    
setReminder :: Long -> IO ()
setReminder n = do
        println ("Ok, I remind you in " ++ show n ++ " seconds")
        Thread.sleep (1000L*n)
        println (show n ++ " seconds is up!")

table = "table"
            
mainPhil _ = do
    [fork1,fork2,fork3,fork4,fork5] <- mapM MVar.new [1..5]
    forkIO (philosopher "Kant" fork5 fork1)
    forkIO (philosopher "Locke" fork1 fork2)
    forkIO (philosopher "Wittgenstein" fork2 fork3)
    forkIO (philosopher "Nozick" fork3 fork4)
    forkIO (philosopher "Mises" fork4 fork5)
    return ()    

philosopher :: String -> MVar Int -> MVar Int -> IO ()
philosopher me left right = do
    g <- Random.newStdGen
    let phil g  = do
            let (tT,g1) = Random.randomR (60L, 120L) g
                (eT, g2)  = Random.randomR (80L, 160L) g1
                thinkTime = 300L * tT
                eatTime   = 300L * eT
    
            println(me ++ " is going to the dining room and takes his seat.") 
            fl <- left.take            
            println (me ++ " takes up left fork (" ++ show fl ++ ")")
            rFork <- right.poll
            case rFork of
                Just fr -> do 
                    println (me ++ " takes up right fork. (" ++ show fr ++ ")") 
                    println (me ++ " is going to eat for " ++ show eatTime ++ "ms")
                    Thread.sleep eatTime
                    println (me ++ " finished eating.")
                    right.put fr
                    println (me ++ " took down right fork.")
                    left.put fl
                    println (me ++ " took down left fork.")
                    table.notifyAll 
                    println(me ++ " is going to think for " ++ show thinkTime ++ "ms.")
                    Thread.sleep thinkTime
                    phil g2
                Nothing -> do
                    println (me ++ " finds right fork is already in use.")
                    left.put fl
                    println (me ++ " took down left fork.")
                    table.notifyAll
                    println (me ++ " is going to the bar to await notifications from table.")
                    table.wait
                    println (me ++ " got notice that something changed at the table.")
                    phil g2
            
        inter :: InterruptedException -> IO ()
        inter _ = return ()        
    
    phil g `catch` inter

    
getURL xx = do
        url <- URL.new xx 
        con <- url.openConnection
        con.connect
        is  <- con.getInputStream
        typ <- con.getContentType
        -- stderr.println ("content-type is " ++ show typ) 
        ir  <- InputStreamReader.new is (fromMaybe "UTF-8" (charset typ))
            `catch` unsupportedEncoding is 
        br  <- BufferedReader.new ir
        br.getLines
    where
        unsupportedEncoding :: InputStream -> UnsupportedEncodingException -> IO InputStreamReader
        unsupportedEncoding is x = do
            stderr.println x.catched
            InputStreamReader.new is "UTF-8"
            
        charset ctyp = do
            typ <- ctyp
            case typ of
                m~´charset=(\S+)´ -> m.group 1
                _ -> Nothing

    
type SomeException = Throwable

main ["dining"] = mainPhil []
        
main _ =  do
    m1 <- MVar.newEmpty
    m2 <- MVar.newEmpty
    m3 <- MVar.newEmpty
    
    forkIO do
        r <- (catchAll . getURL) "http://www.wikipedia.org/wiki/Haskell"
        m1.put r
    
    forkIO do
        r <- (catchAll . getURL) "htto://www.wikipedia.org/wiki/Java"
        m2.put r
    
    forkIO do
        r <- (catchAll . getURL) "http://www.wikipedia.org/wiki/Frege"
        m3.put r
    
    r1 <- m1.take
    r2 <- m2.take
    r3 <- m3.take
    println (result r1, result r2, result r3)
    -- case r3 of
    --     Right ss -> mapM_ putStrLn ss
    --     Left _   -> return ()
  where
    result :: (SomeException|[String]) -> (String|Int)
    result (Left x)  = Left x.getClass.getName
    result (Right y) = (Right . sum . map length)  y
    -- mapM_ putStrLn r2

        