package guitests.guihandles;

import static org.junit.Assert.assertTrue;

import java.util.List;
import java.util.Optional;
import java.util.Set;

import guitests.GuiRobot;
import javafx.scene.Node;
import javafx.scene.control.ListView;
import javafx.stage.Stage;
import seedu.tasklist.TestApp;
import seedu.tasklist.model.task.DeadlineTask;
import seedu.tasklist.model.task.EventTask;
import seedu.tasklist.model.task.ReadOnlyDeadlineTask;
import seedu.tasklist.model.task.ReadOnlyEventTask;
import seedu.tasklist.model.task.ReadOnlyTask;
import seedu.tasklist.testutil.TestUtil;

//@@author A0143355J
public class TodayListPanelHandle extends GuiHandle {

    public static final int NOT_FOUND = -1;
    public static final String CARD_PANE_ID = "#cardPane";

    private static final String TODAY_LIST_VIEW_ID = "#todayTaskListView";

    public TodayListPanelHandle(GuiRobot guiRobot, Stage primaryStage) {
        super(guiRobot, primaryStage, TestApp.APP_TITLE);
    }

    /*
     * Returns a ListView<ReadOnlyTask> of tasks inside TodayListPanel
     */
    public ListView<ReadOnlyTask> getTodayListView() {
        return getNode(TODAY_LIST_VIEW_ID);
    }

    public boolean isTodayListMatching(ReadOnlyTask... tasks) {
        return this.isTodayListMatching(0, tasks);
    }

    public boolean isTodayListMatching(int startPosition, ReadOnlyTask... tasks) throws IllegalArgumentException {
        if (tasks.length + startPosition != getTodayListView().getItems().size()) {
            throw new IllegalArgumentException("List size mismatched\n" +
                    "Expected " + (getTodayListView().getItems().size() - 1) + " tasks");
        }
        assertTrue(this.containsInOrder(startPosition, tasks));
        for (int i = 0; i < tasks.length; i++) {
            final int scrollTo = i + startPosition;
            guiRobot.interact(() -> getTodayListView().scrollTo(scrollTo));
            guiRobot.sleep(200);
            if (!TestUtil.compareUpcomingCardAndTask(getUpcomingTaskCardHandle(startPosition + i), tasks[i])) {
                return false;
            }
        }
        return true;
    }

    public boolean containsInOrder(int startPosition, ReadOnlyTask... tasks) {
        List<ReadOnlyTask> taskList = getTodayListView().getItems();

     // Return false if the list in panel is too short to contain the given list
        if (startPosition + tasks.length > taskList.size()) {
            return false;
        }

        // Return false if any of the tasks doesn't match
        for (int i = 0; i < tasks.length; i++) {
            if (!taskList.get(startPosition + i).getName().fullName.equals(tasks[i].getName().fullName)) {
                return false;
            }
        }

        return true;
    }

    /**
     * Gets a task from the list by index
     */
    public ReadOnlyTask getTask(int index) {
        return getTodayListView().getItems().get(index);
    }

    public UpcomingTaskCardHandle getUpcomingTaskCardHandle(int index) {
        ReadOnlyTask current = getTodayListView().getItems().get(index);
        String type = current.getType();
        switch (type) {
        case DeadlineTask.TYPE:
            return getUpcomingTaskCardHandle(new DeadlineTask((ReadOnlyDeadlineTask) current));
        case EventTask.TYPE:
            return getUpcomingTaskCardHandle(new EventTask((ReadOnlyEventTask) current));
        default:
            return null;
        }
    }

    public UpcomingTaskCardHandle getUpcomingTaskCardHandle(ReadOnlyTask task) {
        Set<Node> nodes = getAllCardNodes();
        Optional<Node> taskCardNode = nodes.stream()
                .filter(n -> new UpcomingTaskCardHandle(guiRobot, primaryStage, n).isSameTask(task))
                .findFirst();

        if (taskCardNode.isPresent()) {
            return new UpcomingTaskCardHandle(guiRobot, primaryStage, taskCardNode.get());
        } else {
            return null;
        }
    }

    protected Set<Node> getAllCardNodes() {
        return guiRobot.lookup(CARD_PANE_ID).queryAll();
    }
}

@@ -2746,24 +2746,1495 @@
 rue;%0A    %7D%0A%0A
+    public UpcomingTaskCardHandle navigateToTask(String name) %7B%0A        guiRobot.sleep(500); //Allow a bit of time for the list to be updated%0A        final Optional%3CReadOnlyTask%3E task = getTodayListView().getItems().stream()%0A                                                    .filter(p -%3E p.getName().fullName.equals(name))%0A                                                    .findAny();%0A        if (!task.isPresent()) %7B%0A            throw new IllegalStateException(%22Name not found: %22 + name);%0A        %7D%0A%0A        return navigateToTask(task.get());%0A    %7D%0A%0A    /**%0A     * Navigates the listview to display and select the task.%0A     */%0A    public UpcomingTaskCardHandle navigateToTask(ReadOnlyTask task) %7B%0A        int index = getTaskIndex(task);%0A%0A        guiRobot.interact(() -%3E %7B%0A            getTodayListView().scrollTo(index);%0A            guiRobot.sleep(150);%0A            getTodayListView().getSelectionModel().select(index);%0A        %7D);%0A        guiRobot.sleep(100);%0A%0A        return getUpcomingTaskCardHandle(task);%0A    %7D%0A%0A    /**%0A     * Returns the position of the task given, %7B@code NOT_FOUND%7D if not found in the list.%0A     */%0A    public int getTaskIndex(ReadOnlyTask targetTask) %7B%0A        List%3CReadOnlyTask%3E tasksInList = getTodayListView().getItems();%0A        for (int i = 0; i %3C tasksInList.size(); i++) %7B%0A            if (tasksInList.get(i).getName().equals(targetTask.getName())) %7B%0A                return i;%0A            %7D%0A        %7D%0A        return NOT_FOUND;%0A    %7D%0A%0A
     /**%0A    

add navigateToTask in TodayListPanelHandle