//@@author A0143157J
package seedu.taskboss.logic.parser;

import java.util.List;
import java.util.Locale;
import java.util.Optional;

import com.joestelmach.natty.DateGroup;

import seedu.taskboss.commons.exceptions.IllegalValueException;
import seedu.taskboss.model.task.DateTime;

/*
 * Parses date
 */
public class DateTimeParser {

    private static final String ERROR_INVALID_DATE = "Failed to understand given date.";
    private static final String ERROR_MULTIPLE_DATES = "Please only enter a single date.";
    private static final String REGEX_US_DATE = "(\\d{1,2})-(\\d{1,2})-((?:\\d\\d){1,2})";
    private static final String REGEX_NON_US_DATE = "$2-$1-$3";
    private static final String EMPTY_STRING = "";

    private com.joestelmach.natty.Parser nattyParser;

    public DateTimeParser() {
        this.nattyParser = new com.joestelmach.natty.Parser();
    }

    /**
     * Returns if a given {@code String date} is a valid date input
     * Used in DateTime class
     */
    public boolean isParseable(String date) {
        List<DateGroup> tempDateGroupList = this.nattyParser.parse(date);
        int numDates = countDates(tempDateGroupList);

        return numDates >= 1;
    }

    public List<DateGroup> parse(String date) {
        String currentDate = date;
        if (Locale.getDefault().equals(Locale.US)) {
            currentDate = date.replaceAll(REGEX_US_DATE, REGEX_NON_US_DATE);
        }

        List<DateGroup> dateGroupList = this.nattyParser.parse(currentDate);
        return dateGroupList;
    }

    /**
     * Parses a given {@code String date}
     * @return parsed DateTime object
     */
    public DateTime parseDate(String date) throws IllegalValueException {
        List <DateGroup> dateGroupList = parse(date);
        int numDates = countDates(dateGroupList);

        if (!date.equals(EMPTY_STRING) && numDates == 0) {
            throw new IllegalValueException(ERROR_INVALID_DATE);
        } else if (numDates > 1) {
            throw new IllegalValueException(ERROR_MULTIPLE_DATES);
        }

        DateGroup dateGroup = dateGroupList.get(0);

        return new DateTime(dateGroup.getDates().get(0), dateGroup.isDateInferred(), dateGroup.isTimeInferred());
    }

    public Optional<String> convert(Optional<DateTime> dateTime) {
        return dateTime.isPresent() ? Optional.of(dateTime.toString()) : Optional.empty();
    }

    private int countDates(List<DateGroup> dateGroups) {
        int numTotalDates = 0;
        for (DateGroup dateGroup : dateGroups) {
            numTotalDates += dateGroup.getDates().size();
        }
        return numTotalDates;
    }

    // for testing
    public static String getInvalidDateError() {
        return ERROR_INVALID_DATE;
    }

    // for testing
    public static String getMultipleDatesError() {
        return ERROR_MULTIPLE_DATES;
    }
}

@@ -103,35 +103,8 @@
 ale;
-%0Aimport java.util.Optional;
 %0A%0Aim
@@ -267,16 +267,60 @@
 ses date
+ and returns a DateTime object for execution
 %0A */%0Apub
@@ -1207,32 +1207,121 @@
 es %3E= 1;%0A    %7D%0A%0A
+    /**%0A     * Parses a given %7B@code String date%7D%0A     * @return List%3CDateGroup%3E%0A     */%0A
     public List%3C
@@ -1661,42 +1661,105 @@
   * 
-Parses a given %7B@code String date%7D
+Calls helper parse() to parse a given %7B@code String date%7D%0A     * and verifies accepted date input
 %0A   
@@ -2399,168 +2399,97 @@
     
-public Optional%3CString%3E convert(Optional%3CDateTime%3E dateTime) %7B%0A        return dateTime.isPresent() ? Optional.of(dateTime.toString()) : Optional.empty();
+/**%0A     * Returns number of DateGroup present in a given %7B@code List%3CDateGroup%3E%7D
 %0A    
-%7D%0A
+ */
 %0A   

Update header comments and remove convert()::DateTimeParser