package com.atlassian.webdriver.bitbucket.element;

import com.atlassian.pageobjects.elements.query.Poller;
import com.atlassian.pageobjects.elements.query.Queries;
import com.atlassian.pageobjects.elements.query.TimedQuery;
import com.atlassian.pageobjects.elements.timeout.TimeoutType;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.collect.Iterables;
import org.hamcrest.Matchers;
import org.openqa.selenium.By;

import java.util.List;

import static org.hamcrest.Matchers.equalTo;


public class GeneralCommentForm extends CommentForm<GeneralCommentForm> {

    public GeneralCommentForm(By locator, TimeoutType timeoutType) {
        super(locator, timeoutType);
    }

    private List<Comment> getGeneralComments() {
        return elementFinder.findAll(By.cssSelector("#pull-request-activity .comment"), Comment.class);
    }

    private TimedQuery<Iterable<Comment>> getGeneralCommentsQuery() {
        return Queries.forSupplier(timeouts, new Supplier<Iterable<Comment>>() {
            @Override
            public Iterable<Comment> get() {
                return getGeneralComments();
            }
        });
    }

    @Override
    public Comment submit() {
        final List<Comment> oldComments = submitComment();
        Poller.waitUntil(getGeneralCommentsQuery(), Matchers.<Comment>iterableWithSize(oldComments.size() + 1));
        return getNewComment(oldComments);
    }

    public void submitExpectingErrors() {
        submitComment();
        Poller.waitUntil(Queries.forSupplier(timeouts, new Supplier<Boolean>() {
            @Override
            public Boolean get() {
                return hasErrors();
            }
        }), equalTo(true));
    }

    public void expand() {
        // If we don't focus, then sometimes the form doesn't expand :(
        getTextArea().javascript().form().focus();
        waitForSubmitButton();
    }

    private List<Comment> submitComment() {
        // find a list of all general comments already on the page
        final List<Comment> oldComments = getGeneralComments();
        expand();
        getCommentButton().click();
        return oldComments;
    }

    private void waitForSubmitButton() {
        Poller.waitUntilFalse(timed().hasClass("collapsed"));
    }

    private Comment getNewComment(List<Comment> oldComments) {
        final List<Long> oldIds = toIdList(oldComments);
        return Iterables.find(getGeneralComments(), new Predicate<Comment>() {
            @Override
            public boolean apply(Comment comment) {
                return !oldIds.contains(comment.getCommentId());
            }
        });
    }

    @Override
    public GeneralCommentForm setText(String text) {
        expand();
        getTextArea().clear().type(text);
        return this;
    }
}
