-- ----------------------------------------------------------------------------
{- |
  Module     : Holumbus.Distribution.Master.MasterState
  Copyright  : Copyright (C) 2010 Sebastian Reese
  License    : MIT

  Maintainer : Stefan Schmidt (stefanschmidt@web.de)
  Stability  : experimental
  Portability: portable
  Version    : 0.1


-}
-- ----------------------------------------------------------------------------

module Holumbus.Distribution.Master.MasterState 
(
    State
  , States
  , StateResource
  , addResource
  , delResource
  , addWorker
  , delWorker
)where

import qualified Data.List as List
import qualified Data.Map                                as Map
import           System.IO.Unsafe
import           Control.Concurrent.MVar
import           Holumbus.MapReduce.Types
import           Holumbus.Common.FileHandling
import qualified Holumbus.Distribution.Worker.WorkerPort as WP
import           Holumbus.Network.Communication
import           Holumbus.Network.Port

type States = Map.Map IdType State
type State = ([ActionName], WP.WorkerPort)
type StateResource = FilePath

{-# NOINLINE resources #-}
resources :: MVar [StateResource]
resources = unsafePerformIO $ newMVar ([])

addResource :: FilePath -> IO ()
addResource fp = do
  modifyMVar_ resources (return . (fp:))
  updateStats

delResource :: FilePath -> IO ()
delResource fp = do
  modifyMVar_ resources (return . List.delete fp)
  updateStats                      

{-# NOINLINE states #-}
states :: MVar States
states = unsafePerformIO $ newMVar (Map.empty)

addWorker :: IdType -> State -> IO ()
addWorker i state = do
  modifyMVar_ states (return . Map.insert i state)
  updateStats

delWorker :: IdType -> IO ()
delWorker i = do
  modifyMVar_ states (return . Map.delete i)
  updateStats

updateStats :: IO ()
updateStats = do
  resources' <- readMVar resources
  states'    <- readMVar states
  clearResources resources'
  putState resources' states'
    
putState :: [StateResource] -> States -> IO ()
putState ress = mapM_ ( flip printState ress ) . Map.toList
    
printState :: (IdType,State) -> [StateResource] -> IO ()
printState (i,(actions, wp)) = mapM_ (flip appendToTextFile (mkLine i wp actions))

clearResources :: [StateResource] -> IO ()
clearResources = mapM_ (flip writeToTextFile $"")

mkLine :: IdType -> WP.WorkerPort -> [ActionName] -> String
mkLine i wp actions = (show i)++"\t"++(showActions actions)++"\t"++(showWorkerPort wp)++ "\n"

showActions :: [ActionName] -> String
showActions [] = ""
showActions (x:[]) = x
showActions (x:xs) = x ++ " / " ++ showActions xs

showWorkerPort :: WP.WorkerPort -> String
showWorkerPort (WP.WorkerPort (ClientPort (Port _ m))) = case m of
  Nothing                     -> "no socket"
  (Just (SocketId host port)) -> host ++ ":" ++ show port