
package seedu.taskmanager.model.task;

import java.util.Date;
import java.util.Objects;
import java.util.Optional;

import seedu.taskmanager.commons.exceptions.IllegalValueException;
import seedu.taskmanager.commons.util.CollectionUtil;
import seedu.taskmanager.commons.util.NotificationUtil;
import seedu.taskmanager.logic.parser.DateTimeUtil;
//import seedu.taskmanager.model.TaskNotifier;
import seedu.taskmanager.model.TaskNotifierManager;
import seedu.taskmanager.model.tag.UniqueTagList;

/**
 * Represents a Task in the task manager. Guarantees: details are present and not null, field values are validated.
 */
public class Task implements ReadOnlyTask {

    private Name name;
    // @@author A0140417R
    private Optional<TaskDate> startDate, endDate;
    private UniqueTagList tags;
    private boolean isDoneStatus;
    private boolean isDueSoonStatus;

    public Task(Name name, TaskDate startDate, TaskDate endDate, UniqueTagList tags, boolean status,
            boolean dueSoonStatus) {
        assert !CollectionUtil.isAnyNull(name, tags);
        this.name = name;
        this.startDate = Optional.ofNullable(startDate);
        this.endDate = Optional.ofNullable(endDate);
        this.tags = new UniqueTagList(tags); // protect internal tags from
                                             // changes in the arg list
        this.isDoneStatus = status;
        this.isDueSoonStatus = dueSoonStatus;
    }

    public Task(Name name, TaskDate startDate, TaskDate endDate, UniqueTagList tags, boolean status) {
        this(name, startDate, endDate, tags, status, false);
        setDueSoonStatus();
    }

    // @@author A0140538J
    public Task(Name name, TaskDate startDate, TaskDate endDate, UniqueTagList tags) {
        this(name, startDate, endDate, tags, false);
    }

    public Task(Name name, UniqueTagList tags) {
        this(name, null, null, tags, false);
    }

    public Task(Name name, Optional<TaskDate> startDate, Optional<TaskDate> endDate, UniqueTagList tags) {
        this(name, startDate.orElse(null), endDate.orElse(null), tags, false);
    }

    /**
     * Creates a copy of the given ReadOnlyTask.
     */
    public Task(ReadOnlyTask source) {
        this(source.getName(), source.getStartDate(), source.getEndDate(), source.getTags(), source.isDone(),
                source.isDueSoon());
    }

    public void setName(Name name) {
        assert name != null;
        this.name = name;
    }

    @Override
    public Name getName() {
        return name;
    }

    // @@author A0140417R
    public void setStartDate(TaskDate taskDate) {
        this.startDate = Optional.ofNullable(taskDate);
    }

    @Override
    public TaskDate getStartDate() {
        return startDate.orElse(null);
    }

    public void removeStartDate() {
        this.startDate = Optional.empty();
    }

    @Override
    public boolean hasStartDate() {
        return startDate.isPresent();
    }

    public void setEndDate(TaskDate taskDate) {
        this.endDate = Optional.ofNullable(taskDate);
    }

    @Override
    public TaskDate getEndDate() {
        return endDate.orElse(null);
    }

    public void removeEndDate() {
        this.endDate = Optional.empty();
    }

    @Override
    public boolean hasEndDate() {
        return endDate.isPresent();
    }

    @Override
    public boolean isFloating() {
        return !hasStartDate() && !hasEndDate();
    }

    @Override
    public boolean isDeadline() {
        return !hasStartDate() && hasEndDate();
    }

    @Override
    public boolean isEvent() {
        return hasStartDate() && hasEndDate();
    }

    public boolean isValidTask() {
        return isFloating() || isDeadline()
                || (isEvent() && startDate.get().getTaskDate().before(endDate.get().getTaskDate()));
    }

    // @@author A0140538J
    public void setDoneStatus(boolean status) {
        this.isDoneStatus = status;
    }

    @Override
    public boolean isDone() {
        return isDoneStatus;
    }

    public void setDueSoonStatus() {
        // TODO to be fixed later
        Date notificationDate = NotificationUtil.getNotificationDate();
        if (notificationDate == null) {
            try {
                notificationDate = DateTimeUtil.parseDateTime(TaskNotifierManager.DEFAULT_NOTIFICATION).getTaskDate();
            } catch (IllegalValueException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        if (this.hasStartDate()) {
            if (getStartDate().getTaskDate().before(notificationDate)) {
                this.isDueSoonStatus = true;
                return;
            }
        }

        if (this.hasEndDate()) {
            if (getEndDate().getTaskDate().before(notificationDate)) {
                this.isDueSoonStatus = true;
                return;
            }
        }

        this.isDueSoonStatus = false;
    }

    @Override
    public boolean isDueSoon() {
        return isDueSoonStatus;
    }
    // @@author

    @Override
    public UniqueTagList getTags() {
        return new UniqueTagList(tags);
    }

    /**
     * Replaces this task's tags with the tags in the argument tag list.
     */
    public void setTags(UniqueTagList replacement) {
        tags.setTags(replacement);
    }

    /**
     * Updates this task with the details of {@code replacement}.
     */
    public void resetData(ReadOnlyTask replacement) {
        assert replacement != null;

        this.setName(replacement.getName());
        this.setStartDate(replacement.getStartDate());
        this.setEndDate(replacement.getEndDate());
        this.setTags(replacement.getTags());
        this.setDoneStatus(replacement.isDone());
    }

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

    @Override
    public int hashCode() {
        // use this method for custom fields hashing instead of implementing
        // your own
        return Objects.hash(name, tags);
    }

    @Override
    public String toString() {
        return getAsText();
    }

}

@@ -114,75 +114,8 @@
 l;%0A%0A
-import seedu.taskmanager.commons.exceptions.IllegalValueException;%0A
 impo
@@ -224,159 +224,8 @@
 il;%0A
-import seedu.taskmanager.logic.parser.DateTimeUtil;%0A//import seedu.taskmanager.model.TaskNotifier;%0Aimport seedu.taskmanager.model.TaskNotifierManager;%0A
 impo
@@ -3824,42 +3824,8 @@
 ) %7B%0A
-        // TODO to be fixed later%0A
     
@@ -3895,345 +3895,8 @@
 e();
-%0A        if (notificationDate == null) %7B%0A            try %7B%0A                notificationDate = DateTimeUtil.parseDateTime(TaskNotifierManager.DEFAULT_NOTIFICATION).getTaskDate();%0A            %7D catch (IllegalValueException e) %7B%0A                // TODO Auto-generated catch block%0A                e.printStackTrace();%0A            %7D%0A        %7D
 %0A%0A  

test travis