/*******************************************************************************
 * Copyright © 2004 VHA. All rights reserved
 ******************************************************************************/
package gov.va.med.esr.common.infra;

// Java Classes
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Calendar;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

// Library Classes
import org.apache.commons.lang.Validate;

// Framework Classes

// Common Classes

/**
 * @author Martin Francisco
 */
public class ImpreciseDateStringFormat {
	
	private static final String PATTERN = "([0-9]{4})([0-9]{2})?(00)?(00)?(00)?";

	private static final int GROUP_YEAR = 1;

	private static final int GROUP_MONTH = 2;

	private static final String FORMAT_MONTH = "00";

	private final Calendar calendar;

	private final String string;

	public ImpreciseDateStringFormat(Calendar calendar) {
		super();

		Validate.notNull(calendar, "calendar cannot be null");

		this.calendar = calendar;
		this.string = (calendar.isSet(Calendar.MONTH)) ? this.formatString(
				calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH)) : this
				.formatString(calendar.get(Calendar.YEAR));
	}

	public ImpreciseDateStringFormat(String string) {
		super();

		Validate.notNull(string, "string cannot be null");

		this.calendar = this.parseString(string);
		this.string = string;
	}

	private int convertToInt(String string) {
		return (new Integer(string)).intValue();
	}

	private String formatString(int year) {
		return this.formatYear(year);
	}

	private String formatString(int year, int month) {
		return this.formatYear(year) + this.formatMonth(month);
	}

	private String formatMonth(int month) {
		NumberFormat format = new DecimalFormat("00");

		return format.format(month + 1);
	}

	private String formatYear(int year) {
		NumberFormat format = new DecimalFormat("0000");

		return format.format(year);
	}

	private Calendar parseString(String string) {
		Matcher matcher = Pattern.compile(ImpreciseDateStringFormat.PATTERN)
				.matcher(string);

		if (matcher.matches()) {
			String year = matcher.group(ImpreciseDateStringFormat.GROUP_YEAR);
			String month = matcher.group(ImpreciseDateStringFormat.GROUP_MONTH);

			Calendar calendar = Calendar.getInstance();
			calendar.setLenient(false);
			calendar.clear();

			calendar.set(Calendar.YEAR, this.convertToInt(year));

			if (month != null && !FORMAT_MONTH.equals(month)) {
				calendar.set(Calendar.MONTH, this.convertToInt(month) - 1);
			}

			return calendar;
		}
		else {
			// ASSERT: Should never happen
			throw new RuntimeException(
					"the string is in an invalid imprecise date format");
		}
	}

	public Calendar getCalendar() {
		return this.calendar;
	}

	public String getString() {
		return this.string;
	}
}