#!/usr/bin/python

# Purpose: Creates all annual merge dates files including ramp-ups 
# Usage: Change variables for run days and year.
# Type ./create_merge_dates.py <YYYY>
#
# By James Beidler (Beidler.James@epa.gov) 2/09/10 
#  Requires Python 2.0 +

import calendar, sys

# Run information

# Path to and filename of the holidays file
holidaysPath = "/garnet/oaqps/em_v5/ge_dat/holidays_04may2006_v0.txt"

# Path to output files
outPath = "."

### End Variable Section.  You should not have to change anything past this point.


# Pass an error if the command line is incorrect
if len(sys.argv) != 2 or len(sys.argv[1]) != 4:
        print "You must pass a single argument of a four digit base year. "
        print "./create_merge_dates.py <YYYY>"
        sys.exit()

year = sys.argv[1]
base_year = int(year)

def fixLength(inDate):
	# Add the appropriate number of 0s to the beginning of a date
	if len(inDate) == 1: return "0" + inDate
	else: return inDate

def isHoliday(inDate, run_hols, run_day):
	# Check if a date is a holiday
	if run_day in run_hols: return run_day
	else: return inDate


def holidaysDict(holidaysPath):
	# Parse holidays file and create dictionary of holidays by month
	holDict = {}
	holidaysFile = file(holidaysPath, 'r')
	for holidayLine in holidaysFile.readlines():
		
		if year in holidayLine[14:20]:
			holMon = holidayLine[8:10]
		elif str(base_year - 1) in holidayLine[14:20] and holidayLine[8:10] == '12':
			holMon = '%s12' %(base_year - 1)
		else: continue 

		if holMon not in holDict: holDict[holMon] = []
		dayAfter = str(int(holidayLine[11:13]) + 1)
		holDict[holMon].append(holidayLine[11:13])
		holDict[holMon].append(fixLength(dayAfter))

	return holDict

cal_year = base_year 
# Find a year that works with the python calendar module
while (cal_year > 2037):  # Python 2.2 calendar module rejects years < 1970 and > 2037  
	cal_year = cal_year - 28	

# Generate the holidays dictionary
holDict = holidaysDict(holidaysPath) 

# Loop for each month, starting with the ramp-up
for month in range(13):
	if month == 0:
		# Use settings for ramp-up
		run_year = base_year - 1
		cal_loop_year = cal_year - 1
		month = 12
		run_hols = holDict['%s12' %run_year]
		outFileName = 'smk_merge_dates_%s12.txt' %run_year
	else:
		run_year = base_year
		cal_loop_year = cal_year
		if fixLength(str(month)) in holDict: run_hols = holDict[fixLength(str(month))]
		else: run_hols = []

		outFileName = 'smk_merge_dates_%s%s.txt' %(run_year, fixLength(str(month)))
	outFile = open('%s/%s' %(outPath, outFileName), 'w')

	# Find aveday representative day in the base year
	for cal_day in range(1, calendar.monthrange(base_year, month)[1] + 1):
		day_of_week = calendar.weekday(base_year, month, cal_day)
		if day_of_week == 1 and cal_day != 1 and fixLength(str(cal_day)) not in run_hols:
			ave_rep = fixLength(str(cal_day))
			break	

	# Find representative week in the base year 
	for week in calendar.monthcalendar(base_year, month):
		hol_match = [day for day in week if fixLength(str(day)) in run_hols]
		if 1 not in week and len(hol_match) == 0:
			rep_list = week
			break	

	cal_my = str(base_year) + fixLength(str(month))

	# Write header
	outFile.write ('    Date, aveday_N, aveday_Y,  mwdss_N,  mwdss_Y,   week_N,   week_Y,      all\n')

	# Loop for each day in the month of the calendar year
	for cal_day in range(1, calendar.monthrange(cal_loop_year, month)[1] + 1):
		day_of_week = calendar.weekday(cal_loop_year, month, cal_day) # Find the day of the week in the calendar year
		rep_day = str(rep_list[day_of_week])     # determine the rep day
		if day_of_week in range(1,5): rep_day = str(rep_list[1])  # set rep weekday
		rep_day = fixLength(rep_day)
		run_day = fixLength(str(cal_day))

		runDate = str(run_year) + fixLength(str(month)) + run_day
		avedayN = cal_my + ave_rep
		avedayY = cal_my + isHoliday(ave_rep, run_hols, run_day)
		mwdssN = cal_my + rep_day
		mwdssY = cal_my + isHoliday(rep_day, run_hols, run_day)
		weekN = cal_my + fixLength(str(rep_list[day_of_week])) 
		weekY = cal_my + isHoliday(fixLength(str(rep_list[day_of_week])), run_hols, run_day) 

		day_list = (runDate, avedayN, avedayY, mwdssN, mwdssY, weekN, weekY, runDate)
		outFile.write('%s\n' %', '.join(day_list))

