package com.atlassian.webdriver.bitbucket.element;

import com.atlassian.pageobjects.PageBinder;
import com.atlassian.pageobjects.elements.PageElement;
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.Lists;
import org.openqa.selenium.By;

import javax.inject.Inject;
import java.util.List;

import static com.atlassian.bitbucket.util.Chainable.chain;

public class CommitList extends LegacyElementPageObject {

    public CommitList(PageElement listContainer) {
        super(listContainer);
    }

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

    public List<CommitListEntry> getRows() {
        return chain(findAll(Locators.tableRow())).transform(row -> pageBinder.bind(CommitListEntry.class, row)).toList();
    }

    public List<String> getColumnNames() {
        final List<PageElement> headers = findAll(By.tagName("th"));
        return Lists.transform(headers, PageElement::getText);
    }

    public void loadNextPage() {
        ElementUtils.scrollDocumentAndWait(this);
    }

    public static class CommitListEntry {

        @Inject
        private PageBinder pageBinder;

        private final PageElement rowElement;

        public CommitListEntry(PageElement rowElement) {
            this.rowElement = rowElement;
        }

        public String getAuthor() {
            return rowElement.find(By.cssSelector("td.author")).getText();
        }

        public Avatar getAuthorAvatar() {
            return rowElement.find(By.cssSelector("td.author .user-avatar"), Avatar.class);
        }

        public String getMessage() {
            return rowElement.find(By.cssSelector("td.message")).getText();
        }

        public String getCommitId() {
            return rowElement.find(By.cssSelector("td.commit > a")).getText();
        }

        public String getCommitHash() {
            return rowElement.find(By.cssSelector("td.commit > a"), LinkElement.class).getUrl().replaceAll(".*?commits\\/", "");
        }

        public Boolean isMerge() {
            return rowElement.find(By.cssSelector("td.commit > .merge-lozenge")).isPresent();
        }

        public String getMachineDate() {
            return rowElement.find(By.cssSelector("td.timestamp > time")).getAttribute("datetime");
        }

        public String getCommitDate() {
            return rowElement.find(By.cssSelector("td.timestamp > time")).getAttribute("title");
        }

        /**
         * Get call at {@code columnIndex} in this row, represented by an instance of {@code columnClass}. The page
         * object represented by {@code columnClass} <i>must</i> provide a constructor accepting a single argument
         * of type {@link PageElement}, or otherwise a runtime error will occur.
         *
         * @param columnIndex 0-based index of the column in the commit row
         * @param columnClass page object class representing the cell
         * @param <T> cell page object generic type
         * @return instance of a page object representing the cell
         */
        public <T> T getPluginColumn(int columnIndex, Class<T> columnClass) {
            return pageBinder.bind(columnClass, rowElement.find(By.xpath("td[" + (columnIndex + 1) + "]")));
        }

        public boolean hasBuildStatus() {
            return rowElement.find(By.className("build-icon")).isPresent();
        }

        public BuildStatusDialog clickBuildStatus() {
            rowElement.find(By.cssSelector("td.build-status-commit-list-col > .build-icon")).click();
            return pageBinder.bind(BuildStatusDialog.class, By.id("build-status-dialog"), TimeoutType.DIALOG_LOAD);
        }
    }

    public static class JiraIssueColumnCell {

        private final PageElement cellElement;

        public JiraIssueColumnCell(PageElement cellElement) {
            this.cellElement = cellElement;
        }

        public String getTriggerText() {
            List<LinkElement> a = cellElement.findAll(By.tagName("a"), LinkElement.class);
            return a.get(0).getText();
        }
    }
}
