-- |
-- = A Module for Calendar Information
module Calendar (Month, Year, Dayname, monthInfo) where

{-| 1 - January, 2 - February, ... -}
type Month   = Int
{-| Years are just 'Int's. -}
type Year    = Int
{-| 0 - Sunday, 1 - Monday, 2 - Tuesday, ... -}
type Dayname = Int

{-| Given a month and a year, return the first weekday of the month
    together with the total number of days it has (in the given year). -}
monthInfo :: Month -> Year -> (Dayname, Int)
monthInfo m y = zip (firstDaysOfYear y) (monthLengths y) !! (m - 1)

firstDaysOfYear :: Year -> [Dayname]
firstDaysOfYear = take 12 . map (`mod` 7) . monthTotals

monthTotals :: Year -> [Int]
monthTotals y = scanl (+) (january1 y) (monthLengths y)

monthLengths :: Year -> [Int]
monthLengths y = [31,feb,31,30,31,30,31,31,30,31,30,31]
  where
    feb = if leap y then 29 else 28

leap :: Year -> Bool
leap y =
  if y `mod` 100 == 0 then (y `mod` 400 == 0)
  else (y `mod` 4 == 0)

january1 :: Year -> Dayname
january1 y = (365*x + x `div` 4 - x `div` 100 + x `div` 400 + 1) `mod` 7
  where
    x = y - 1