package seedu.watodo.model.task;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;

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

import seedu.watodo.commons.exceptions.IllegalValueException;

//@@author A0143076J
/**
 * Represents a Task's start time, end time or deadline in the task manager.
 * Guarantees: immutable; is valid as declared in {@link #isValidDateTime(String)}
 */
public class DateTime {

    public static final String MESSAGE_DATETIME_CONSTRAINTS = "Date and time format must be a date/day, time or both";
    public static final Parser DATE_TIME_PARSER = new Parser(TimeZone.getDefault());  //Parser class in natty library

    public final Calendar dateTime;

    /**
     * Validates given DateTime.
     *
     * @throws IllegalValueException if given dateTime string is invalid.
     */
    public DateTime(String dateString) throws IllegalValueException {
        assert dateString != null;
        String trimmedDateString = dateString.trim();
        if (!isValidDateTime(trimmedDateString)) {
            throw new IllegalValueException(MESSAGE_DATETIME_CONSTRAINTS);
        }
        this.dateTime = convertToCalendarFormat(trimmedDateString);
    }

    /**
     * Returns true if a given string is a valid date time.
     */
    public static boolean isValidDateTime(String dateTime) {
        List<DateGroup> parsedDateGroups = DATE_TIME_PARSER.parse(dateTime);
        return parsedDateGroups.size() == 1 && !parsedDateGroups.get(0).getDates().isEmpty();
    }

    /**
     * Converts the given string into a standard Date format of year, month, date, hour, minutes and seconds.
     * Precondition: the String dateTime has already been checked to be valid
     */
    private Calendar convertToCalendarFormat(String dateString) {
        List<DateGroup> parsedDateGroups = DATE_TIME_PARSER.parse(dateString);
        Calendar cal = Calendar.getInstance();
        cal.setTime(parsedDateGroups.get(0).getDates().get(0));

        //if no timing is given by the user, default timing of 11.59pm is set.
        Date currDate = new Date();
        SimpleDateFormat timeFormatter = new SimpleDateFormat("hh:mm:ssa", Locale.ENGLISH);
        if (timeFormatter.format(currDate).equals(timeFormatter.format(cal.getTime()))) {
            cal.set(Calendar.HOUR, 11);
            cal.set(Calendar.MINUTE, 59);
            cal.set(Calendar.SECOND, 00);
            cal.set(Calendar.MILLISECOND, 00);
            cal.set(Calendar.AM_PM, Calendar.PM);
        }
        return cal;
    }

    /* Checks if the current DateTime is at a later date than another given DateTime */
    public boolean isLater(DateTime other) {
        return this.dateTime.after(other.dateTime);
    }

    @Override
    public String toString() {
        Date currDate = new Date();
        Calendar currCal = Calendar.getInstance();
        currCal.setTime(currDate);

        if (dateTime.get(Calendar.YEAR) != (currCal.get(Calendar.YEAR))) {
            //only shows the year if the date is not in the current year
            SimpleDateFormat dateFormatter = new SimpleDateFormat("EEE d MMM yy, h.mma", Locale.ENGLISH);
            return dateFormatter.format(dateTime.getTime());
        }
        SimpleDateFormat dateFormatter = new SimpleDateFormat("EEE d MMM, h.mma", Locale.ENGLISH);
        return dateFormatter.format(dateTime.getTime());
    }

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

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

}

@@ -543,16 +543,123 @@
 Time %7B%0A%0A
+    private static final int INDEX_VALID_DATE = 0;%0A    private static final String DATESTRING_NOW = %22now%22;%0A
     publ
@@ -769,16 +769,16 @@
  both%22;%0A
-
     publ
@@ -1700,33 +1700,48 @@
 dDateGroups.get(
-0
+INDEX_VALID_DATE
 ).getDates().isE
@@ -2192,17 +2192,32 @@
 ups.get(
-0
+INDEX_VALID_DATE
 ).getDat
@@ -2225,17 +2225,32 @@
 s().get(
-0
+INDEX_VALID_DATE
 ));%0A%0A   
@@ -2445,32 +2445,100 @@
 ocale.ENGLISH);%0A
+        if (!dateString.toLowerCase().equals(DATESTRING_NOW)) %7B%0A    
         if (time
@@ -2615,32 +2615,36 @@
 ) %7B%0A            
+    
 cal.set(Calendar
@@ -2655,16 +2655,20 @@
 R, 11);%0A
+    
         
@@ -2705,32 +2705,36 @@
 9);%0A            
+ 
+   
 cal.set(Calendar
@@ -2739,32 +2739,36 @@
 ar.SECOND, 00);%0A
+    
             cal.
@@ -2802,32 +2802,36 @@
 0);%0A            
+    
 cal.set(Calendar
@@ -2852,16 +2852,30 @@
 ar.PM);%0A
+            %7D%0A
         

fix the datetime such that reads correctly if given time is "now"