#!/usr/bin/ruby

#
## http://rosettacode.org/wiki/Calendar#Sidef
#

require('DateTime')

define months_per_col = 3
define week_day_names = <Mo Tu We Th Fr Sa Su>
define month_names = <Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec>

func fmt_month (year, month) {
    var str = sprintf("%-20s\n", month_names[month-1])
    str += week_day_names.join(' ')+"\n"

    var dt = %s<DateTime>
    var date = dt.new(year => year, month => month)
    var week_day = date.day_of_week
    str += (week_day-1 `of` "  " -> join(" "))

    var last_day = dt.last_day_of_month(year => year, month => month).day
    for day (date.day .. last_day) {
        date = dt.new(year => year, month => month, day => day)
        str += " " if (week_day ~~ (2..7))
        if (week_day == 8) {
            str += "\n"
            week_day = 1
        }
        str += sprintf("%2d", day)
        ++week_day
    }
    str += " " if (week_day < 8)
    str += (8-week_day `of` "  " -> join(" "))
    str += "\n"
}

func fmt_year (year) {
    var month_strs = 12.of {|i| fmt_month(year, i+1).lines }

    var str = (' '*30 + year + "\n")
    for month (0..11 `by` months_per_col) {
        while (month_strs[month]) {
            for i (1..months_per_col) {
                month_strs[month + i - 1] || next
                str += month_strs[month + i - 1].shift
                str += ' '*3
            }
            str += "\n"
        }
        str += "\n"
    }

    return str
}

print fmt_year(ARGV ? Number(ARGV[0]) : 1969)
