package it.com.atlassian.stash.tasks;

import com.atlassian.pageobjects.elements.query.Poller;
import com.atlassian.bitbucket.content.DiffSegmentType;
import com.atlassian.webdriver.bitbucket.element.Comment;
import com.atlassian.webdriver.bitbucket.element.tasks.PullRequestTaskListDialog;
import com.atlassian.webdriver.bitbucket.element.tasks.Task;
import com.atlassian.webdriver.bitbucket.element.tasks.TaskState;
import com.atlassian.webdriver.bitbucket.element.tasks.TaskTable;
import com.atlassian.webdriver.bitbucket.page.PullRequestDiffPage;
import com.atlassian.webdriver.bitbucket.page.PullRequestOverviewPage;
import org.apache.commons.io.FilenameUtils;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

public class PullRequestTaskDialogUITest extends BasePullRequestTaskUITest {

    protected static final String FILE_PATH = "basic_branching/file.txt";

    @Test
    public void testTaskListDialogWithNoTask() throws Exception {
        PullRequestOverviewPage pullRequestOverviewPage = goToPullRequest(pullRequest);

        PullRequestTaskListDialog dialog = pullRequestOverviewPage.openTaskListDialogWithKeyboardShortcut();
        assertTrue(dialog.isEmpty());
        dialog.close();
    }

    @Test
    public void testTaskListDialogWithOneTask() throws Exception {
        PullRequestOverviewPage pullRequestOverview = goToPullRequest(pullRequest);
        Comment comment = pullRequestOverview.getGeneralCommentAt(0);
        comment.createTask(TASK_TEXT);

        PullRequestTaskListDialog dialog = pullRequestOverview.openTaskListDialog();
        assertEquals("Table should have one task", 1, dialog.getTaskCount());
        dialog.close();
        Poller.waitUntilFalse("Task list dialog is closed", dialog.timed().isVisible());
    }

    @Test
    public void testTaskListDialogWithTaskAddedAfterOpening() throws Exception {
        PullRequestOverviewPage pullRequestOverview = goToPullRequest(pullRequest);
        PullRequestTaskListDialog dialog = pullRequestOverview.openTaskListDialogWithKeyboardShortcut();
        dialog.close();

        Comment comment = pullRequestOverview.getGeneralCommentAt(0);
        comment.createTask(TASK_TEXT);

        dialog = pullRequestOverview.openTaskListDialogWithKeyboardShortcut();
        assertEquals("Table should have one task", 1, dialog.getTaskCount());
    }

    /**
     * This test will check state changes properly propagate between the task list
     * dialog and the activity stream. It achieves this by:
     *
     *  - creating a task
     *  - resolve the task via the task list dialog
     *  - close dialog and assert the state changed in the activity stream
     *  - create and resolve a task in the activity stream
     *  - open the task list dialog and check that it is resolved
     *  - reopen it via the dialog
     *  - assert it is open again in the activity stream
     *
     * @throws Exception
     */
    @Test
    public void testTaskListDialogStateChanges() throws Exception {
        PullRequestOverviewPage pullRequestOverview = goToPullRequest(pullRequest);

        Comment comment = pullRequestOverview.getGeneralCommentAt(1);
        comment.createTask(TASK_TEXT);

        PullRequestTaskListDialog dialog = pullRequestOverview.openTaskListDialog();
        TaskTable.Row taskRow = dialog.getRowByCommentId(comment.getCommentId());
        assertEquals(TaskState.OPEN, taskRow.getState());

        taskRow.resolveTask();

        dialog.close();
        assertEquals(TaskState.RESOLVED, comment.getTaskAt(0).getState());

        comment = pullRequestOverview.getGeneralCommentAt(2);
        Task task = comment.createTask(TASK_TEXT2);
        task.resolve();

        pullRequestOverview.openTaskListDialogWithKeyboardShortcut();

        taskRow = dialog.getRowByCommentId(comment.getCommentId());
        assertEquals(TaskState.RESOLVED, taskRow.getState());

        taskRow.reopenTask();
        assertEquals(TaskState.OPEN, taskRow.getState());

        dialog.close();

        assertEquals(TaskState.OPEN, task.getState());
    }

    @Test
    public void testTaskListDialogWithFileComment() throws Exception {
        String COMMENT_TEXT = "Comment reply!!";

        pullRequest.addDiffComment("Diff comment", FILE_PATH, 1, DiffSegmentType.ADDED);

        PullRequestDiffPage pullRequestDiff = goToPullRequestDiff(pullRequest);

        Comment parentComment = pullRequestDiff.getCommentAt(0);
        parentComment.createTask(TASK_TEXT);
        long parentCommentId = parentComment.getCommentId();

        Comment reply = parentComment.replyWith(COMMENT_TEXT);
        reply.createTask(TASK_TEXT2);
        long replyCommentId = reply.getCommentId();

        PullRequestOverviewPage pullRequestOverview = pullRequestDiff.switchToOverview();
        assertEquals(2, pullRequestOverview.waitForOpenTaskCountPanel(true));

        PullRequestTaskListDialog dialog = pullRequestOverview.openTaskListDialog();

        TaskTable.Row taskRow = dialog.getRowByCommentId(parentCommentId);
        assertEquals(TASK_TEXT, taskRow.getText());
        assertEquals(FILE_PATH, taskRow.getFilePath());
        assertEquals(FilenameUtils.getName(FILE_PATH), taskRow.getFileName());

        TaskTable.Row replyTaskRow = dialog.getRowByCommentId(replyCommentId);
        assertEquals(TASK_TEXT2, replyTaskRow.getText());
        assertEquals(FILE_PATH, replyTaskRow.getFilePath());
        assertEquals(FilenameUtils.getName(FILE_PATH), replyTaskRow.getFileName());
    }

    @Test
    public void testTaskListDialogDeleteTask() throws Exception {
        PullRequestOverviewPage pullRequestOverview = goToPullRequest(pullRequest);
        Comment comment = pullRequestOverview.getGeneralCommentAt(0);
        comment.createTask(TASK_TEXT);

        PullRequestTaskListDialog dialog = pullRequestOverview.openTaskListDialog();

        TaskTable.Row taskRow = dialog.getRowByCommentId(comment.getCommentId());
        taskRow.deleteTask();

        dialog.close();

        assertEquals(0, pullRequestOverview.waitForOpenTaskCountPanel(false));
    }

    @Test
    public void testTaskListDialogWithTasksNotOnScreen() throws Exception {
        PullRequestOverviewPage pullRequestOverview = goToPullRequest(pullRequest);

        Comment secondPageComment = pullRequestOverview.getGeneralCommentAt(0);
        long secondPageCommentId = secondPageComment.getCommentId();
        secondPageComment.createTask("second page task");

        // Push the comment holding the off-screen task into a second page of activity
        for (int i = 0; i < PullRequestOverviewPage.PAGE_SIZE; ++i) {
            pullRequest.addGeneralComment("filler comment " + i);
        }

        // reload the page so the second-page task is no longer there
        pullRequestOverview = goToPullRequest(pullRequest);

        Comment firstPageComment = pullRequestOverview.getGeneralCommentAt(0);
        long firstPageCommentId = firstPageComment.getCommentId();
        firstPageComment.createTask("first page task");

        PullRequestTaskListDialog dialog = pullRequestOverview.openTaskListDialog();
        assertEquals("Table should have two tasks", 2, dialog.getTaskCount());
        assertEquals("first page task", dialog.getRowByCommentId(firstPageCommentId).getText());
        assertEquals("second page task", dialog.getRowByCommentId(secondPageCommentId).getText());
    }
}
