package seedu.address.model.filter;

import java.time.LocalDate;
import java.time.LocalDateTime;

import seedu.address.model.task.DeadlineTask;
import seedu.address.model.task.EventTask;
import seedu.address.model.task.FloatingTask;
import seedu.address.model.task.Task;

/**
 * A predicate that returns true if the {@link Task} happens today/in the reference.
 * <p><ul>
 * <li> Floating tasks all happens today if {@link FloatingTask#isFinished()} returns false.
 * <li> Deadline tasks happens today when {@link DeadlineTask#getDue()} is in reference date
 *      and when {@link DeadlineTask#isFinished()} returns false.
 * <li> Event tasks happens today when their end time is before the end time of the reference date
 *      and after the reference datetime.
 * </ul>
 */
public class TaskWillHappenTodayPredicate implements TaskPredicate {
    private final LocalDateTime referenceDateTime;
    private final LocalDate today;
    private final LocalDate tomorrow;

    public TaskWillHappenTodayPredicate(LocalDateTime referenceDateTime) {
        assert referenceDateTime != null;
        this.referenceDateTime = referenceDateTime;
        this.today = this.referenceDateTime.toLocalDate();
        this.tomorrow = this.today.plusDays(1);
    }

    @Override
    public boolean test(FloatingTask floatingTask) {
        return !floatingTask.isFinished();
    }

    @Override
    public boolean test(DeadlineTask deadlineTask) {
        return deadlineTask.getDue().isAfter(today.atStartOfDay())
               && deadlineTask.getDue().isBefore(tomorrow.atStartOfDay())
               && !deadlineTask.isFinished();
    }

    @Override
    public boolean test(EventTask eventTask) {
        return eventTask.getEnd().isAfter(referenceDateTime)
               && eventTask.getEnd().isBefore(tomorrow.atStartOfDay());
    }

    @Override
    public String toHumanReadableString() {
        return "finished tasks today";
    }

    @Override
    public boolean equals(Object other) {
        return other == this
               || (other instanceof TaskWillHappenTodayPredicate
               && referenceDateTime.equals(((TaskWillHappenTodayPredicate)other).referenceDateTime));
    }

}

@@ -662,16 +662,22 @@
 n their 
+start/
 end time
@@ -750,24 +750,132 @@
 e reference 
+datetime or the start time is before the reference datetime and the end%0A *      time is after the reference 
 datetime.%0A *
@@ -1877,16 +1877,19 @@
         
+   
 && event
@@ -1935,16 +1935,292 @@
 OfDay())
+%0A               %7C%7C eventTask.getStart().isAfter(referenceDateTime)%0A                  && eventTask.getStart().isBefore(tomorrow.atStartOfDay())%0A               %7C%7C eventTask.getEnd().isAfter(referenceDateTime)%0A                  && eventTask.getStart().isBefore(referenceDateTime)
 ;%0A    %7D%0A

update TaskWillHappenTodayPredicate