package com.atlassian.webdriver.bitbucket.element;

import com.atlassian.pageobjects.elements.PageElement;
import com.atlassian.pageobjects.elements.query.Poller;
import com.atlassian.pageobjects.elements.timeout.TimeoutType;
import com.atlassian.webdriver.bitbucket.util.ElementUtils;
import com.atlassian.webdriver.bitbucket.util.Locators;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import org.openqa.selenium.By;

import java.util.List;

import static com.atlassian.webdriver.bitbucket.util.ElementUtils.bind;

public class PullRequestTable extends AbstractElementPageObject {

    public PullRequestTable(PageElement pageElement) {
        super(pageElement);
    }

    public Iterable<String> getColumnNames() {
        return Iterables.transform(findAll(By.tagName("th")), PageElement::getText);
    }

    public String getCurrentTimestamp() {
        Poller.waitUntilTrue(container.timed().isVisible());
        return container.getAttribute("data-last-updated");
    }

    public List<Entry> getRows() {
        Poller.waitUntilFalse(container.find(By.className("bb-spinner")).timed().isPresent());
        return Lists.transform(container.findAll(Locators.tableRow(), TimeoutType.PAGE_LOAD), bind(pageBinder, Entry.class)::apply);
    }

    public void loadNextPage() {
        waitUntilEventFired("bitbucket.internal.pull.request.list.updated",
                () -> {
                    ElementUtils.scrollDocument(container);
                    Poller.waitUntilFalse(container.find(By.className("bb-spinner")).timed().isPresent());
                });
    }

    public void waitUntilTableIsUpdated(String currentTimestamp) {
        Poller.waitUntilFalse(container.timed().hasAttribute("data-last-updated", currentTimestamp));
    }

    public static class Entry extends AbstractElementPageObject {

        public Entry(PageElement pageElement) {
            super(pageElement);
        }

        public String getAuthorName() {
            return getAuthorElement().getText();
        }

        public String getAuthorUsername() {
            return getAuthorElement().find(By.cssSelector("span.user-avatar")).getAttribute("data-username");
        }

        public BuildStatusDialog getBuildStatusDialog() {
            // Wait for build status as it is loaded asynchronously
            Poller.waitUntilTrue(container.find(By.cssSelector("td.build-status-pr-list-col-value > .build-icon")).timed().isPresent());
            container.find(By.cssSelector("td.build-status-pr-list-col-value > .build-icon")).click();
            return pageBinder.bind(BuildStatusDialog.class, By.id("build-status-dialog"), TimeoutType.DIALOG_LOAD);
        }

        public long getId() {
            String linkValue = this.find(By.cssSelector("td.summary > div.title-and-target-branch > a.pull-request-title")).getAttribute("href");
            return Long.parseLong(linkValue.split("/")[linkValue.split("/").length - 2]);
        }

        public int getOpenTaskCount() {
            PageElement count =
                    container.find(By.cssSelector("td.count-column-value.tasks > span > span.count"), TimeoutType.DEFAULT);
            return count.timed().isPresent().byDefaultTimeout() ? Integer.parseInt(count.getText()) : 0;
        }

        /**
         * @return the reviewers that are directly visible (not the ones hidden behind the "N more" item)
         */
        public List<Participant> getReviewers() {
            return container.findAll(By.cssSelector(".reviewer-avatar-list > .user-avatar"), Participant.class);
        }

        public String getTargetBranch() {
            return this.find(By.cssSelector("td.summary > div.title-and-target-branch > span.pull-request-target-branch")).getText();
        }

        public String getTitle() {
            return this.find(By.cssSelector("td.summary > div.title-and-target-branch > a.pull-request-title")).getText();
        }

        public boolean hasBuildStatus() {
            // Wait for build status as it is loaded asynchronously
            Poller.waitUntilTrue(container.find(By.cssSelector("td.build-status-pr-list-col-value")).timed().isPresent());
            return container.find(By.cssSelector("td.build-status-pr-list-col-value > .build-icon")).isPresent();
        }

        private PageElement getAuthorElement() {
            return this.find(By.cssSelector("td.summary > div.author-and-timestamp > div.avatar-with-name"));
        }
    }
}
