{- DisTract ------------------------------------------------------\
 |                                                                 |
 | Copyright (c) 2007, Matthew Sackman (matthew@wellquite.org)     |
 |                                                                 |
 | DisTract is freely distributable under the terms of a 3-Clause  |
 | BSD-style license. For details, see the DisTract web site:      |
 |   http://distract.wellquite.org/                                |
 |                                                                 |
 \-----------------------------------------------------------------}

module DisTract.Utils
    (readFileStrict,
     writeFileStrict,
     bugIdTimeFormatter,
     monotoneDateFormat,
     monotoneDateFormatLength,
     bugIdDateFormat,
     bugIdDateFormatLength,
     humanTimeFormat,
     intersperseEvery,
     formatTimeHuman
    )
where

import System.IO
import Data.Time
import Data.Fixed
import System.Locale

readFileStrict :: FilePath -> IO String
readFileStrict file = do { h <- openFile file ReadMode
                         ; str <- hGetContents h
                         ; length str `seq` return ()
                         ; hClose h
                         ; return str
                         }

writeFileStrict :: FilePath -> String -> IO ()
writeFileStrict file txt = do { h <- openFile file WriteMode
                              ; hPutStr h txt
                              ; hClose h
                              }

bugIdTimeFormatter :: UTCTime -> String
bugIdTimeFormatter t@(UTCTime { utctDayTime = fromMidnight })
    = time ++ "S" ++ millis
    where
      time = formatTime defaultTimeLocale bugIdDateFormat
             t
--              pico = 10^-12; milli = 10^-3; hence 10^9
--              | - chop off anything smaller than 1 ms  - |
      millis' = (fromMidnight - (fromMidnight `mod'` 0.001)) `mod'` 1
      millis'' = show ((floor . toRational . (*1000) $ millis') :: Integer)
      padding = replicate (3 - (length millis'')) '0'
      millis = padding ++ millis''

bugIdDateFormat :: String
bugIdDateFormat = "%Y%m%dT%H%M%S"

bugIdDateFormatLength :: Int -- assumes that we don't hit the year 10000
bugIdDateFormatLength = 4 + 2 + 2 + 1 + 2 + 2 + 2
--                      %Y  %m  %d  T   %H  %M  %S

monotoneDateFormat :: String
monotoneDateFormat = "%Y-%m-%dT%H:%M:%S"

monotoneDateFormatLength :: Int -- assumes that we don't hit the year 10000
monotoneDateFormatLength = 4 + 1 + 2 + 1 + 2 + 1 + 2 + 1 + 2 + 1 + 2
--                         %Y  -   %m  -   %d  T   %H  :   %M  :   %S

humanTimeFormat :: String
humanTimeFormat = "%c"

intersperseEvery :: Int -> a -> [a] -> [a]
intersperseEvery n sep list
    = intersperseEvery' n 1 sep list
      where
        intersperseEvery' _ _ _ [] = []
        intersperseEvery' _ _ _ [x] = [x]
        intersperseEvery' n t sep (x:xs)
            | n == t = x : sep : intersperseEvery n sep xs
            | otherwise = x : intersperseEvery' n (t+1) sep xs

formatTimeHuman :: (FormatTime t) => t -> IO String
formatTimeHuman t
    = do { return $ formatTime defaultTimeLocale humanTimeFormat t}