var monthNames = new Array();
/*monthNames[1]="January"; monthNames[2]="February"; monthNames[3]="March"; 
monthNames[4]="April"; monthNames[5]="May"; monthNames[6]="June"; 
monthNames[7]="July"; monthNames[8]="August"; monthNames[9]="September"; 
monthNames[10]="October"; monthNames[11]="November"; monthNames[12]="December"; */

monthNames[1]="01"; monthNames[2]="02"; monthNames[3]="03"; 
monthNames[4]="04"; monthNames[5]="05"; monthNames[6]="06"; 
monthNames[7]="07"; monthNames[8]="08"; monthNames[9]="09"; 
monthNames[10]="10"; monthNames[11]="11"; monthNames[12]="12";

var shortMonthNames = new Array();
shortMonthNames[1]="Jan"; shortMonthNames[2]="Feb"; shortMonthNames[3]="Mar"; 
shortMonthNames[4]="Apr"; shortMonthNames[5]="May"; shortMonthNames[6]="Jun"; 
shortMonthNames[7]="Jul"; shortMonthNames[8]="Aug"; shortMonthNames[9]="Sep"; 
shortMonthNames[10]="Oct"; shortMonthNames[11]="Nov"; shortMonthNames[12]="Dec"; 

var dayNames = new Array();
dayNames[0]="Sunday"; dayNames[1]="Monday"; dayNames[2]="Tuesday"; 
dayNames[3]="Wednesday"; dayNames[4]="Thursday"; dayNames[5]="Friday"; 
dayNames[6]="Saturday"; 

var shortDayNames = new Array();
shortDayNames[0]="Sun"; shortDayNames[1]="Mon"; shortDayNames[2]="Tue"; 
shortDayNames[3]="Wed"; shortDayNames[4]="Thu"; shortDayNames[5]="Fri"; 
shortDayNames[6]="Sat"; 

var dateFormats = new Array();
//dateFormats[1]="dd/MMM yyyy";
//dateFormats[1]="dd/MM/yyyy";
dateFormats[1]="yyyy-MM-dd";
dateFormats[2]="dd-MMM-yy"; dateFormats[3]="dd/MM/yy"; 

// Holds the list of separator chars
var separator = "., /-";
// Holds the pattern chars occuring for date
var patternChars = "dMyE";

function AvailableFormats () { 
	this.LONG = dateFormats[1];
	this.MEDIUM = dateFormats[2];
	this.SHORT = dateFormats[3];
}
var DateFormat = new AvailableFormats();

// Holds the month max value
var monthMax = new Array();
monthMax[0]=31;
monthMax[1]=28;
monthMax[2]=31;
monthMax[3]=30;
monthMax[4]=31;
monthMax[5]=30;
monthMax[6]=31;
monthMax[7]=31;
monthMax[8]=30;
monthMax[9]=31;
monthMax[10]=31;
monthMax[11]=32;

function shortMonth(monthVal) {
	for(k=0; k<shortMonthNames.length; k++) {
		if(shortMonthNames[k] == monthVal)
			return k-1;
	}
}

function month(monthVal) {
	for(k=0; k<monthNames.length; k++) {
		if(monthNames[k] == monthVal)
			return k-1;
	}
}

function dayName(dayVal) {
	for(k=0; k<dayNames.length; k++) {
		if(dayNames[k] == dayVal)
			return k;
	}
}

function shortDayName(dayVal) {
	for(k=0; k<shortDayNames.length; k++) {
		if(shortDayNames[k] == dayVal)
			return k;
	}
}

/*
 * Parses a date against given format
 * this does not include time
 * This will validate date formats which have only day, date, month or year or combinations
 * The separator chars should be above listed
 * Atleast one separator should exist between each token
 */
function parseDateString(checkdate, format) {
	if(format.indexOf("?") != -1)
		return false;

	// Run a loop on format string to check if invalid chars exist
	for(i=0; i<format.length; i++) {
		// Pick the current char
		var curChar = format.charAt(i);
		if(separator.indexOf(curChar) == -1 && patternChars.indexOf(curChar) == -1) {
			return false;
		}
	}

	// Append a separator in end to run loop until end for both
	checkdate += " ";
	format += " ";

	// Holds the parsed values
	var parseMonth ;
	var parseDate ;
	var parseYear ;
	var parseDay ;

	// If format string does not have modifier, allow default as current
	if(format.indexOf('d') == -1)
		parseDate = new Date().getDate();
	if(format.indexOf('M') == -1)
		parseMonth = new Date().getMonth();
	if(format.indexOf('y') == -1)
		parseYear = new Date().getFullYear();
	
	// Holds the prev char
	var prevChar = format.charAt(0);
	// find the repeat count of format char
	var repeatCount = 0;

	// Holds the cursor on date String
	var cursor = 0;
	
	// Run a loop on format string
	for(i=0; i<format.length; i++) {
		// Pick the current char
		var curChar = format.charAt(i);
		// If prev char is not current char, format sub object ends
		// Validation should be done
		if(prevChar != curChar) {
			// If cur char is not separator, start counting repeat count, and increment cursor also
			// Assign prev char, as it would not hit the final else
			if(separator.indexOf(curChar) == -1) {
				prevChar = curChar;
				repeatCount++;
				cursor++;
				continue;
			}

			// Parse the current token
			var tokenIndex = checkdate.indexOf(curChar, cursor);

			// If token index is -1, parsing error separator does not match pattern
			if(tokenIndex == -1)
				return false;

			// pick current token
			var token = checkdate.substring(cursor, tokenIndex);

			// update cursor
			cursor = tokenIndex;

			// validate each modifier

			// If modifier is date
			if(prevChar == 'd') {
				// Switch on repeat count
				switch (repeatCount) {
					// Date should be compulsory 2 digit
					case 2 :
						// Validate length
						if(token.length != 2)
							return false;
						break;
					case 1 :
						// Date cannot be more than two chars
						if(token.length > 2)
							return false;
						break;
				}
				// Check the validity of date
				if(isNaN(new Number(token)))
					return false;
				// Assign new value to data holder
				parseDate = new Number(token);

				// Reset repeat count
				repeatCount = 0;

			// If modifier is month
			} else if(prevChar == 'M') {
				// Local month holder
				var loopMon ;

				// Switch on repeat count
				switch (repeatCount) {
					// validate full month string over respective array
					// if length is 4 or 3, and assign correct value
					case 4 :
						if(month(token) == null)
							return false;
						loopMon = month(token);
						break;
					case 3 :
						if(shortMonth(token) == null)
							return false;
						loopMon = shortMonth(token);
						break;
					// If 2, month should have 2 digits compulsory
					case 2 :
						if(token.length != 2)
							return false;
					// Validate month value and assign
					case 1 :
						if(token.length > 2)
							return false;
						var calMonth = new Number(token);
						if(isNaN(calMonth))
							return false
						// Calculate the array index of month
						loopMon = calMonth-1;
						break;
				}
				// Validate month value
				if(loopMon > 11)
					return false;
				// Assign value to data holder
				parseMonth = loopMon;

				// reset repeat count
				repeatCount = 0;

			// if modifier is year
			} else if(prevChar == 'y') {
				// Digits should exactly match specified pattern
				if(token.length != repeatCount)
					return false;
				// Check year validity
				if(isNaN(new Number(token)))
					return false;
				else {
					// Calculate full year
					var calYear = new Number(token);
					// Convert to full year if it is of 2 digits
					if(calYear < 100) {
						if(calYear < 50)
							token = "20"+token;
						else
							token = "19"+token;
					}
				}
				// Assign it to data holder
				parseYear = new Number(token);

				// Reset repeat count
				repeatCount = 0;
			} else if(prevChar == 'E') {
				var loopDayNum ;
				// Switch on repeat count
				switch (repeatCount) {
					// validate day name over respective array
					// if length is 4 or 3, Assign correct value
					case 4 :
						if(dayName(token) == null)
							return false;
						loopDayNum = dayName(token);
						break;
					case 3 :
					case 2 :
						if(shortDayName(token) == null)
							return false;
						loopDayNum = shortDayName(token);
						break;
				}
				
				parseDay = loopDayNum;
				// Validate and ignore day name as it would 
				// automatically be calculated
			}
			// Validate exact match of separator chars to pattern
			if(separator.indexOf(curChar) != -1) {
				if(checkdate.charAt(cursor) != curChar)
					return false;
				repeatCount=0;
			}

		} else {
			// Just increment the repeat count if prev and curr chars are same
			repeatCount++;
		}
		// Assign curr char to prev
		prevChar = curChar;
	}
	// Trim the added space on both formatter and date string
	checkdate=checkdate.replace(/^\s+|\s+$/ig, '');
	format=format.replace(/^\s+|\s+$/ig, '');
	// Validate if all fields are correctly extracted
	if((format.indexOf('d') != -1 && parseDate == null) || (format.indexOf('M') != -1 && parseMonth == null)
		|| (format.indexOf('y') != -1 && parseYear == null) || (format.indexOf('E') != -1 && parseDay == null)) {
		return false;
	} else {
		// Validate max value of date
		max = 31;
		// If month is existing, validate date againt month
		if(parseMonth != null) {
			// Calculate the max possible date value for calculated month
			max = monthMax[parseMonth];
			// If leap year, feb will have 29 days
			if(parseYear != null && parseYear%4 == 0 && parseMonth == 1)
				max ++;
		}
		var retDate ;
		// validate for max exceeded
		if(parseDate > max)
			return false;
		else
			retDate = new Date(parseYear,parseMonth,parseDate); // Return date object with parsed values

		if(parseDay != null && retDate.getDay() != parseDay)
			return false;
		else
			return retDate;
	}
}

/*
 * This method will read a JavaScript Date object
 * Formats it based on specified format
 * this does not include time
 * This will work for date formats which have only day, date, month or year or combinations
 * The separator chars should be above listed
 */
function formatDate(dateObj, format) {
	// Temp string to hold formatted data
	var temp = "";
	// Append one separator for loop to work until end
	format += " ";

	// Holds the prev char
	var prevChar = format.charAt(0);
	// find the repeat count of format char
	var repeatCount = 0;

	// Get the values to use
	var parseMonth = dateObj.getMonth()+1;
	var parseDate = dateObj.getDate();
	var parseYear = dateObj.getFullYear();
	var parseDay = dateObj.getDay();

	// Run a loop on format string
	for(i=0; i<format.length; i++) {
		// Pick the current char
		var curChar = format.charAt(i);
		// If prev char is not current char, format sub object ends
		// Validation should be done
		if(prevChar != curChar) {
			// If curr char is a separator, start counting
			// assign cur char to prev char
			if(separator.indexOf(curChar) == -1) {
				prevChar = curChar;
				repeatCount++;
				continue;
			}

			// For each modifier, fetch and append accordingly
			if(prevChar == 'd') {
				switch (repeatCount) {
					case 2 :
						var xy = "00"+parseDate;
						temp+=xy.substring(xy.length-2,xy.length);
						break;
					case 1 :
						temp+=parseDate;
						break;
				}
				repeatCount = 0;
			} else if(prevChar == 'M') {
				switch (repeatCount) {
					case 4 :
						temp += monthNames[parseMonth];
						break;
					case 3 :
						temp += shortMonthNames[parseMonth];
						break;
					case 2 :
						var xy = "00"+parseMonth;
						temp+=xy.substring(xy.length-2,xy.length);
						break;
					case 1 :
						temp += parseMonth;
						break;
				}
				repeatCount = 0;
			} else if(prevChar == 'y') {
				switch (repeatCount) {
					case 4 :
						temp += parseYear;
						break;
					case 2 :
						var xy = ""+parseYear;
						temp += xy.substring(xy.length-2,xy.length);
						break;
				}
				repeatCount = 0;
			} else if(prevChar == 'E') {
				switch (repeatCount) {
					case 4 :
						temp += dayNames[parseDay];
						break;
					case 3 :
					case 2 :
						temp += shortDayNames[parseDay]
						break;
				}
			}
			// Append the separator and reset count
			if(format.indexOf(curChar) != -1) {
				temp+=curChar;
				repeatCount=0;
			}

		} else {
			// Just increment count if both prev and curr are same
			repeatCount++;
		}

		// Assign cur char to prev char
		prevChar = curChar;
	}
	// Trim the added space
	format=format.replace(/^\s+|\s+$/ig, '');
	temp=temp.replace(/^\s+|\s+$/ig, '');

	// Return formatted value
	return temp;
}

