#!/usr/bin/env ascript

# calendar

calendar(year:number, weekOffset:number = 0, nCols:number = 3) = {
	calOfMonth(year:number, month:number) = {
		offsetFirst = (time.weekday(year, month, 1) + 7 - weekOffset) % 7
		days = [fill(offsetFirst, "  "),
				(1..time.monthdays(year, month)).format("%2d")]
		days.fold(7).align(6, []):*align(7, "  "):*join(" ")
	}
	monthNames = [
		"", "January", "February", "March", "April", "May", "June",
		"July", "August", "September", "October", "November", "December",
	]
	weekAbbrs = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"]
	weekAbbrs = weekAbbrs.round(7 + weekOffset).offset(weekOffset):list
	weekLine = weekAbbrs.join(" ")
	wdPerMonth = 3 * 7 - 1
	wdSep = 6
	sep = " " * wdSep
	rtn = []
	rtn.add!(format("%04d", year).align((wdPerMonth + wdSep) * nCols - wdSep):center)
	rtn.add!("")
	repeat (math.ceil(12 / nCols)) {|iRow|
		month = iRow * nCols + 1
		nColsCur = choosemin(nCols, 12 - month + 1)
		months = [month..(month + nColsCur - 1)]
		rtn.add!((monthNames[months]:*align(wdPerMonth):center).join(sep))
		rtn.add!(repeat(nColsCur):list { weekLine }.join(sep))
		lines = repeat(6):list { "" }
		repeat (nColsCur) {|iCol|
			if (iCol > 0) { lines += sep }
			lines += calOfMonth(year, month + iCol)
		}
		rtn.add!(lines)
	}
}
year = if (sys.argv.len() < 2) {
	time.localtime().year()
} else {
	tonumber(sys.argv[1])
}
println(calendar(year))
