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 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) {
        try {
	    // Format input string to suit Natty dependency
	    String formattedInitialTaskDate = changeToNattyDateFormat(taskDate);
	    this.value = nattyManipulation(formattedInitialTaskDate);
        } catch (ParseException pe) {
            this.value = nattyManipulation(taskDate);
        }
    }

    /**
     * Uses Natty dependency (natural language date parser) to manipulate date
     * input in String.
     */
    private String nattyManipulation(String taskDate) {
 
	try {
            // Initialises Natty parser
            Parser parser = new Parser();

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

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

            // Format parsed date to suit the regex
            String formattedFinalTaskDate = changeToUserDateFormat(parsedDate);
            
            return formattedFinalTaskDate;
            
	} catch (IndexOutOfBoundsException e) {
	    return taskDate;
	}

    }

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

	String output = new String();
	Date userDateObject = userDateFormat.parse(input);
	output = nattyDateFormat.format(userDateObject);

	return output;
    }

    /**
     * Changes the final date format of a Date input for user.
     */
    private 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);
    }
}

@@ -336,193 +336,8 @@
 e;%0A%0A
-    public final SimpleDateFormat userDateFormat = new SimpleDateFormat(USER_DATE_FORMAT);%0A    public final SimpleDateFormat nattyDateFormat = new SimpleDateFormat(NATTY_DATE_FORMAT);%0A%0A
     
@@ -396,16 +396,23 @@
  = %22%5E$%7C(
+0%5B1-9%5D%7C
 %5B12%5D%5B0-9
@@ -422,21 +422,14 @@
 %5B01%5D
-%7C0?%5B1-9%5D)/
+)%5B/%5D
 (0
-?
 %5B1-9
@@ -441,26 +441,129 @@
 12%5D)
-/((?:
+%5B/%5D(
 19%7C20)
-%5C%5Cd%5C%5Cd)
+%5B0-9%5D%7B2%7D (2%5B0-3%5D%7C%5B0-1%5D%5B0-9%5D)%5B:%5D%5B0-5%5D%5B0-9%5D%22;%0A    public static final String USER_DATE_INPUT_FORMAT = %22dd/MM/yyyy
 %22;%0A 
@@ -598,24 +598,31 @@
 g USER_DATE_
+OUTPUT_
 FORMAT = %22dd
@@ -621,32 +621,37 @@
 AT = %22dd/MM/yyyy
+ H:mm
 %22;%0A    public st
@@ -716,24 +716,25 @@
  zzz yyyy%22;%0A
+%0A
     public s
@@ -736,125 +736,295 @@
 lic 
-static final String MESSAGE_PARSE_EXCEPTION = %22User input date f
+final SimpleDateFormat userInputDateFormat = new SimpleDateFormat(USER_DATE_INPUT_FORMAT);%0A    public final SimpleDateFormat userOutputDateFormat = new SimpleDateFormat(USER_DATE_OUTPUT_FORMAT);%0A    public final SimpleDateF
 ormat 
-to N
+n
 atty
- date f
+DateF
 ormat
-: Parse Exception error!%22;%0A
+ = new SimpleDateFormat(NATTY_DATE_FORMAT);
 %0A   
@@ -1932,13 +1932,10 @@
 the 
-regex
+UI
 %0A   
@@ -1975,33 +1975,38 @@
 kDate = 
-changeToUserDateF
+userOutputDateFormat.f
 ormat(pa
@@ -2379,24 +2379,29 @@
 bject = user
+Input
 DateFormat.p
@@ -2491,188 +2491,8 @@
  %7D%0A%0A
-    /**%0A     * Changes the final date format of a Date input for user.%0A     */%0A    private String changeToUserDateFormat(Date input) %7B%0A%09return userDateFormat.format(input);%0A    %7D%0A%0A
     

Modify constructor to accept time input