module M_lokstatus where

import Mdl

import System.Time
import System.Locale (defaultTimeLocale)
import System.Process
import Data.List
import System.IO
import qualified Data.Map as Map

-- heh heh
backtick :: String -> IO String
backtick cmd
  = do (_, h, _, p) <- runInteractiveCommand cmd
       output <- hGetContents h
       forkIO (waitloop p)
       return output
  where
  -- yes this is dirty. but it doesn't require a threaded runtime.
  waitloop p = do threadDelay 2000000
                  x <- getProcessExitCode p
		  maybe (waitloop p) (\_ -> return ()) x

lok :: Mdl
lok log inp out = do r_ts <- newIORef (Map.empty)
                     v_open <- atomically (newTVar True)
                     -- forkIO (checkstatus v_open)
                     react (f r_ts) inp out
  where
  f r_ts (Msg _ _ _ "332" (_by:chan:topic:_))
    = do modifyIORef r_ts (Map.insert chan topic)
         return []
  f r_ts (Msg from _ _ "TOPIC" (chan:topic:_))
    = do modifyIORef r_ts (Map.insert chan topic)
         return []
  f r_ts (Msg from _ _ "PRIVMSG" (to:"!lok":_))
    = do now <- getClockTime
         status <- backtick (cmd txturl)
         log 2 ("lokstatus="++show status)
         return ["PRIVMSG "++tgt from to++" :"++lokmsg now (lines status)]
  f r_ts (Msg from _ _ "PRIVMSG" (to:"!lokraw":_))
    = do status <- liftM (filter (/='\r')) (backtick (cmd xmlurl ++ xmlfilter))
         return ["PRIVMSG "++tgt from to++" :"++status]
  f r_ts (Msg from _ _ "PRIVMSG" (to:"!lokxml":_))
    = do status <- backtick (cmd xmlurl)
         return ["PRIVMSG "++tgt from to++" :"++status]

  txturl = "http://bananentage.de/rainerfoobarbatnarfkrams.txt"
  xmlurl = "http://bananentage.de/behmacfoobarbatnarfkrams.txt"
  cmd u = "curl '"++u++"'"

  xmlfilter = "| sed -e 's|</[^>]*>|  |g;s|<\\([^>]*\\)>|\\1=|g'"
  
  tgt from to = if isAlpha (head to) then from else to
  
  checkstatus v_open
    = do status <- backtick (cmd txturl)
         log 2 ("lokstatus="++show status)

lokmsg now (date:dhcp:blubber:kogge:wlan:_)
    | age > 2   = "Pff, kann ich hellsehen oder was?"
    | otherwise = "Wir haben "++plural n "host"++" in der dhcp-range, \
                  \"++show m++" im wlan \
                  \und "++bk++". "++oc
    where
    age = hourdiff $ now `diffClockTimes` parselokdate date
    n = read dhcp
    m = if null wlan then 0 else read wlan
    bk
      | b>0        = "blubber ist an"
      | otherwise  = "blubber ist aus"
    b = hostjdg (read blubber)
    k = hostjdg (read kogge)
    oc
      | n>1 = "Sieht offen aus! :)"
      | n<1 = "Sieht zu aus! :("
      | otherwise = ""

    hostjdg p = if p>1 then 1 else 0
      
lokmsg _ _ = "Lokstatus, woher soll ich das wissen?!"

plural n s = show n ++ " " ++ (if n==1 then s else (s++"s"))
  
parselokdate :: String -> ClockTime
parselokdate s = toClockTime caltime
  where
  caltime = CalendarTime { ctYear = read year
                         , ctMonth = toEnum month
                         , ctDay = read day
                         , ctHour = read hour
                         , ctMin = read minute
                         , ctSec = read second
                         , ctPicosec = 0
                         , ctTZ = (if month>2 && month<10 then 2 else 1) * 3600
                         -- none of the rest should be needed
                         , ctWDay = undefined
                         , ctYDay = undefined
                         , ctTZName = undefined
                         , ctIsDST = undefined
                         }
  [day,month',year,hour,minute,second] = splitby "/:" s
  Just month = elemIndex month' monthnames
  monthnames = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]
  splitby ss xs = case break (`elem` ss) xs of
                    ([],[]) -> []
                    (ys,[]) -> [ys]
                    (ys,zs) -> (ys : splitby ss (tail zs))

hourdiff :: TimeDiff -> Double
hourdiff td' = fromIntegral (((years*12 + months)*30 + days)*24 + hours)
               + fromIntegral minutes/60
  where
  TimeDiff {tdYear=years, tdMonth=months, tdDay=days, tdHour=hours, tdMin=minutes}
    = normalizeTimeDiff td'
