import System.Environment
import Control.Monad.State
import Control.Monad.List

type St = (Bool,Int,String)

action (server,client) = get >>= \(isServer,_,_)->if isServer then server else client

line s = action (liftIO $ putStrLn s,liftIO getLine >>= guard . (==s))

getChars 0 cs = return (reverse cs)
getChars n cs = getChar >>= getChars (n-1) . (:cs)

http  = line "HTTP/1.1 200"
len   = action 
        (get >>= \(_,_,b)->line ("Content-Length: "++(show (length b)))
        ,do l <- liftIO getLine 
            let ("Content-Length:",_:b) = span (/=' ') l 
            modify (\(s,_,t)->(s,read b,t))
        ) 
typ   = line "Content-Type: text/plain"
empty = line ""
body  = action
        (get >>= \(_,_,b)->liftIO $ putStr b
        ,get >>= \(s,l,_)->liftIO (getChars l "") >>= \b->put (s,l,b)
        )

protocol = http >> len >> typ >> empty >> body

server = runListT $ runStateT protocol (True,undefined,"this\nis\na\ntext\n")
client = runListT $ runStateT protocol (False,undefined,"")

main = do
  mode:_ <- getArgs
  case mode of
    "server" -> server >> return ()
    "client" -> client >>= mapM_ (\(_,(_,_,text))->putStr text) 
