#!/usr/bin/env python

from __future__ import print_function

import sys
import argparse
from datetime import date;

def makeDate(month, day):
	return date(4, month, day)


class color:
	PURPLE = '\033[95m'
	CYAN = '\033[96m'
	DARKCYAN = '\033[36m'
	BLUE = '\033[94m'
	GREEN = '\033[92m'
	YELLOW = '\033[93m'
	RED = '\033[91m'
	BOLD = '\033[1m'
	UNDERLINE = '\033[4m'
	END = '\033[0m'


# For each key,
# start date, end date, day of week
cal = {
	'Chaos': [makeDate(1,  1),  makeDate(3, 14),  0],
	'Discord': [makeDate(3, 15),  makeDate(5, 26),  3],
	'Confusion': [makeDate(5, 27),  makeDate(8,  7),  1],
	'Bureaucracy': [makeDate(8,  8),  makeDate(10, 19), 4],
	'Aftermath': [makeDate(10, 20), makeDate(12, 31), 2]
}

days = [ 'SM', 'BT', 'PD', 'PP', 'SO' ];

def yearOfDiscord(year):
	# After `X-Day' passed without incident, the Church of the SubGenius
	# declared that it had got the year upside down - X-Day is actually in
	# 8661 AD rather than 1998 AD.  Thus, the True X-Day is Cfn 40, 9827.
	return year+1166

def hasStTibs(year):
	try:
		date(year, 2, 29)
	except ValueError:
		return False
	else:
		return True

def getSeason(month, day):
	greg = makeDate(month, day)
	for season in cal:
		if greg >= cal[season][0] and greg <= cal[season][1]:
			return season

def isStTibs(year, month, day):
	if hasStTibs(year) and month == 2 and day == 29:
		return True
	else:
		return False

def printSeason(year, month, day):
	try:
		if isStTibs(year, month, day):
			print("Today is St. Tib's Day, YOLD {0:d}!".format(yearOfDiscord(year)))
			return
	except:
		print("Date out of range.")
		return
	season = getSeason(month, day)
	dosToday = (makeDate(month, day) - cal[season][0]).days
	print('{0:^18}'.format(season + " " + str(yearOfDiscord(year))))
	print('  ', end='')
	print(' '.join(days))
	dow = cal[season][2]
	print('  ', end='')
	for times in range(dow):
		print('   ', end='')
	for dos in range(0,73):
		if dow > 4:
			dow = 0
			print('')
			print('  ', end='')
		if dos == dosToday:
			print(color.RED + '{0:2d} '.format(dos+1) + color.END, end='')
		else:
			print('{0:2d} '.format(dos+1), end='')
		dow+=1
	print('')

if __name__ == "__main__":
	parser = argparse.ArgumentParser(description='Display the discordian calendar.')
	parser.add_argument('day', type=int, nargs='?', help='Show the calendar for the specified day')
	parser.add_argument('month', type=int, nargs='?', help='Show the calendar for the specified month')
	parser.add_argument('year', type=int, nargs='?', help='Show the calendar for the specified year')
	args = parser.parse_args()
	nargs = len([x for x in (args.year, args.day, args.month) if x is not None])

	try:
		if nargs == 3:
			today = date(args.year, args.month, args.day)
		elif nargs == 0:
			today = date.today()
		else:
			parser.print_help()
			sys.exit(1)
	except ValueError:
		print('Date is out of range.')
		sys.exit(1)
	printSeason(today.year, today.month, today.day)
