package tars.model.task;

import java.time.DateTimeException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.ResolverStyle;

import tars.commons.core.Messages;
import tars.commons.exceptions.IllegalValueException;

/**
 * Represents a Task's dateTime in tars.
 */
public class DateTime implements Comparable<DateTime>{

    public static final String MESSAGE_DATETIME_CONSTRAINTS = "Task datetime should be spaces or alphanumeric characters";

    private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d/M/uuuu HHmm")
            .withResolverStyle(ResolverStyle.STRICT);
    private static final DateTimeFormatter stringFormatter = DateTimeFormatter.ofPattern("dd/MM/uuuu HHmm");
    
    private static final String DATETIME_STRING_TO = " to ";
    private static final String DATETIME_STRING_EMPTY = "";
    
    private static final int DATETIME_SIZE_EMPTY = 0;
    
    private static final int DATETIME_COMPARE_NULL = 1;
    
    private LocalDateTime startDate;
    private LocalDateTime endDate;

    public String startDateString;
    public String endDateString;

    /**
     * Default constructor
     */
    public DateTime() {
    }

    /**
     * Validates given task dateTime.
     *
     * @throws DateTimeException
     *             if given dateTime string is invalid.
     * @throws IllegalDateException
     *             end date occurring before start date.
     */
    public DateTime(String startDate, String endDate) throws DateTimeException, IllegalDateException {
        if (endDate != null && endDate.length() > DATETIME_SIZE_EMPTY) {
            this.endDate = LocalDateTime.parse(endDate, formatter);
            this.endDateString = this.endDate.format(stringFormatter);
        }

        if (startDate != null && startDate.length() > DATETIME_SIZE_EMPTY) {
            this.startDate = LocalDateTime.parse(startDate, formatter);
            this.startDateString = this.startDate.format(stringFormatter);
            if (this.endDate.isBefore(this.startDate) || this.endDate.isEqual(this.startDate)) {
                throw new IllegalDateException(Messages.MESSAGE_INVALID_END_DATE);
            }
        }
    }

    public LocalDateTime getStartDate() {
        return this.startDate;
    }

    public LocalDateTime getEndDate() {
        return this.endDate;
    }

    @Override
    public String toString() {
        if (this.startDate != null && this.endDate != null) {
            return startDateString + DATETIME_STRING_TO + endDateString;
        } else if (this.endDate != null) {
            return endDateString;
        } else {
            return DATETIME_STRING_EMPTY;
        }
    }

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

    /**
     * Signals an error caused by end date occurring before start date
     */
    public class IllegalDateException extends IllegalValueException {
        public IllegalDateException(String message) {
            super(message);
        }
    }

	@Override
	public int compareTo(DateTime o) {
	    if(o.endDate == null || this.endDate == null) {
	        return DATETIME_COMPARE_NULL;
	    } else {
	        return this.endDate.compareTo(o.endDate);
	    }
	}
    
    public void setStartDateTime(LocalDateTime startDate) {
        this.startDate = startDate;
    }
    
    public void setEndDateTime(LocalDateTime endDate) {
        this.endDate = endDate;
    }
    
}

@@ -362,18 +362,19 @@
 ateTime%3E
+ 
 %7B%0A
-
 %0A    pub
@@ -753,21 +753,17 @@
 HHmm%22);%0A
-    
 %0A
+
     priv
@@ -875,21 +875,17 @@
 Y = %22%22;%0A
-    
 %0A
+
     priv
@@ -930,21 +930,17 @@
 TY = 0;%0A
-    
 %0A
+
     priv
@@ -987,21 +987,17 @@
 LL = 1;%0A
-    
 %0A
+
     priv
@@ -2202,24 +2202,366 @@
      %7D%0A    %7D
+%0A    %0A    public DateTime(LocalDateTime startDate, LocalDateTime endDate) %7B%0A        assert(startDate != null && endDate != null);%0A%0A        this.startDate = startDate;%0A        this.endDate = endDate;%0A        this.endDateString = this.endDate.format(stringFormatter);%0A        this.startDateString = this.startDate.format(stringFormatter);%0A    %7D
 %0A%0A    public
@@ -3677,17 +3677,20 @@
 %0A    %7D%0A%0A
-%09
+    
 @Overrid
@@ -3691,17 +3691,20 @@
 verride%0A
-%09
+    
 public i
@@ -3734,15 +3734,19 @@
 ) %7B%0A
-%09
+  
     
+  
 if
+ 
 (o.e
@@ -3787,17 +3787,20 @@
 null) %7B%0A
-%09
+    
         
@@ -3833,87 +3833,571 @@
 LL;%0A
-%09    %7D else %7B%0A%09        return this.endDate.compareTo(o.endDate);%0A%09    %7D%0A%09%7D%0A    
+        %7D else if (o.startDate == null && this.startDate == null) %7B%0A            return this.endDate.compareTo(o.endDate);%0A        %7D else if (o.startDate == null) %7B%0A            return this.startDate.compareTo(o.endDate);%0A        %7D else if (this.startDate == null) %7B%0A            return this.endDate.compareTo(o.startDate);%0A        %7D else %7B%0A            if (this.startDate.equals(o.startDate)) %7B%0A                return this.endDate.compareTo(o.endDate);%0A            %7D else %7B%0A                return this.startDate.compareTo(o.startDate);%0A            %7D%0A        %7D%0A    %7D%0A
 %0A   
@@ -4491,29 +4491,25 @@
 Date;%0A    %7D%0A
-    
 %0A
+
     public v
@@ -4590,15 +4590,11 @@
 ;%0A    %7D%0A
-    
 %0A%7D%0A

Add new constructor in DateTime to take in LocalDateTime objects