package seedu.ezdo.model.todo;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import com.joestelmach.natty.DateGroup;
import com.joestelmach.natty.Parser;

/**
 * Represents the date associated with tasks.
 */
public abstract class TaskDate {

    public final String value;

    public final SimpleDateFormat userDateFormat = new SimpleDateFormat(USER_DATE_FORMAT);
    public final SimpleDateFormat nattyDateFormat = new SimpleDateFormat(NATTY_DATE_FORMAT);

    public static final String TASKDATE_VALIDATION_REGEX = "^$|([12][0-9]|3[01]|0?[1-9])/(0?[1-9]|1[012])/((?:19|20)\\d\\d)";
    public static final String USER_DATE_FORMAT = "dd/MM/yyyy";
    public static final String NATTY_DATE_FORMAT = "EEE MMM dd hh:mm:ss zzz yyyy";
    public static final String MESSAGE_PARSE_EXCEPTION = "User input date format to Natty date format: Parse Exception error!";

    public TaskDate(String taskDate) {

	if (isValidTaskDate(taskDate)) {
	    // Format input string to suit Natty dependency
	    String formattedInitialTaskDate = changeToNattyDateFormat(taskDate);

	    // Use Natty dependency to manipulate date input
	    Date parsedTaskDate = parseNatty(formattedInitialTaskDate);

	    // Format parsed date to suit the regex
	    String formattedFinalTaskDate = changeToUserDateFormat(parsedTaskDate);

	    this.value = formattedFinalTaskDate;

	} else {
	    this.value = new String();
	}

    }

    /**
     * Uses Natty dependency (natural language date parser) to manipulate date
     * input in String.
     */
    public Date parseNatty(String date) {

	// Initialises Natty parser
	Parser parser = new Parser();

	// Parses input String into a list of DateGroups
	List<DateGroup> dateGroupList = parser.parse(date);

	// Retrieves parsed date
	Date parsedDate = dateGroupList.get(0).getDates().get(0);

	return parsedDate;
    }

    /**
     * Changes the initial date format of a string input for Natty.
     */
    public String changeToNattyDateFormat(String input) {

	String output = new String();

	try {
	    Date userDateObject = userDateFormat.parse(input);
	    output = nattyDateFormat.format(userDateObject);
	} catch (ParseException pe) {
	    System.out.println("MESSAGE_PARSE_CONSTRAINTS");
	}

	return output;
    }

    /**
     * Changes the final date format of a Date input for user.
     */
    public String changeToUserDateFormat(Date input) {
	return userDateFormat.format(input);
    }

    @Override
    public String toString() {
	return value;
    }

    @Override
    public boolean equals(Object other) {
	return other == this // short circuit if same object
		|| (other instanceof TaskDate // instanceof handles nulls
			&& this.value.equals(((TaskDate) other).value)); // state
									 // check
    }

    @Override
    public int hashCode() {
	return value.hashCode();
    }

    /**
     * Returns true if a given string is a valid task date.
     */
    public static boolean isValidTaskDate(String test) {
	return test.matches(TASKDATE_VALIDATION_REGEX);
    }
}

@@ -317,22 +317,16 @@
  public 
-final 
 String v
@@ -919,16 +919,21 @@
 ror!%22;%0A%0A
+    %0A
     publ
@@ -967,40 +967,19 @@
 ) %7B%0A
-%0A%09if (isValidTaskDate(taskDate))
+        try
  %7B%0A%09
@@ -1108,100 +1108,43 @@
 e);%0A
-%0A
 %09    
-// Use Natty dependency to manipulate date input%0A%09    Date parsedTaskDate = parseNatty
+this.value = nattyManipulation
 (for
@@ -1171,220 +1171,109 @@
 e);%0A
-%0A%09
     
-// Format parsed date to suit the regex%0A%09    String formattedFinalTaskDate = changeToUserDateFormat(parsedTaskDate);%0A%0A%09    this.value = formattedFinalT
+    %7D catch (ParseException pe) %7B%0A            this.value = nattyManipulation(t
 askDate
+)
 ;%0A
-%0A%09%7D else %7B%0A%09    this.value = new String();%0A%09%7D%0A
+        %7D
 %0A   
@@ -1404,37 +1404,47 @@
    p
-ublic Date parseNatty
+rivate String nattyManipulation
 (String 
 date
@@ -1443,18 +1443,41 @@
 ing 
-d
+taskD
 ate) %7B%0A
+ 
 %0A%09
+try %7B%0A            
 // I
@@ -1500,17 +1500,28 @@
  parser%0A
-%09
+            
 Parser p
@@ -1543,17 +1543,28 @@
 ser();%0A%0A
-%09
+            
 // Parse
@@ -1604,17 +1604,28 @@
 eGroups%0A
-%09
+            
 List%3CDat
@@ -1665,17 +1665,32 @@
 rse(
-d
+taskD
 ate);%0A%0A
-%09
+            
 // R
@@ -1710,17 +1710,28 @@
 ed date%0A
-%09
+            
 Date par
@@ -1781,24 +1781,135 @@
 et(0);%0A%0A
-%09return 
+            // Format parsed date to suit the regex%0A            String formattedFinalTaskDate = changeToUserDateFormat(
 parsedDa
@@ -1910,18 +1910,155 @@
 rsedDate
+)
 ;%0A
+            %0A            return formattedFinalTaskDate;%0A            %0A%09%7D catch (IndexOutOfBoundsException e) %7B%0A%09    return taskDate;%0A%09%7D%0A%0A
     %7D%0A%0A 
@@ -2137,37 +2137,38 @@
 y.%0A     */%0A    p
-ublic
+rivate
  String changeTo
@@ -2196,16 +2196,38 @@
 g input)
+ throws ParseException
  %7B%0A%0A%09Str
@@ -2257,21 +2257,9 @@
 ();%0A
-%0A%09try %7B%0A%09    
+%09
 Date
@@ -2306,20 +2306,16 @@
 nput);%0A%09
-    
 output =
@@ -2358,96 +2358,8 @@
 ct);
-%0A%09%7D catch (ParseException pe) %7B%0A%09    System.out.println(%22MESSAGE_PARSE_CONSTRAINTS%22);%0A%09%7D
 %0A%0A%09r
@@ -2459,29 +2459,30 @@
     */%0A    p
-ublic
+rivate
  String chan

Add try-catch block to accept NLP (ParseException); Add try-catch block to accept optional date parameters (IndexOutOfBoundsException);