package com.atlassian.webdriver.bitbucket.page;

import com.atlassian.bitbucket.util.MoreCollectors;
import com.atlassian.pageobjects.elements.ElementBy;
import com.atlassian.pageobjects.elements.PageElement;
import com.atlassian.pageobjects.elements.WebDriverCheckboxElement;
import com.atlassian.pageobjects.elements.query.Poller;
import org.openqa.selenium.By;

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

public class PullRequestRepositorySettingsPage extends BaseRepositoryPage {

    @ElementBy(className = "merge-strategies")
    private PageElement mergeConfig;
    @ElementBy(id = "requiredApprovers")
    private WebDriverCheckboxElement requiredApprovers;
    @ElementBy(id = "requiredApproversCount")
    private PageElement requiredApproversCount;
    @ElementBy(id = "requirePullRequestTasksResolved")
    private WebDriverCheckboxElement requireTasksCompletedCheckbox;
    @ElementBy(id = "require-all-approvers-for-merge")
    private WebDriverCheckboxElement requireAllApprovalsCheckbox;

    @ElementBy(cssSelector = "form.pull-request-settings #submit")
    private PageElement saveButton;
    @ElementBy(id = "cancel")
    private PageElement cancelLink;

    public PullRequestRepositorySettingsPage(String projectKey, String slug) {
        super(projectKey, slug);
    }

    public void disableMergeStrategies(Set<String> strategyIds) {
        mergeConfig.findAll(By.name("enabledIds")).stream()
                .filter(element -> {
                    String checked = element.getAttribute("checked");
                    return checked != null && strategyIds.contains(element.getId());
                })
                .forEach(PageElement::click);
    }

    public void enableMergeStrategies(Set<String> strategyIds) {
        mergeConfig.findAll(By.name("enabledIds")).stream()
                .filter(element -> {
                    String checked = element.getAttribute("checked");
                    return checked == null && strategyIds.contains(element.getId());
                })
                .forEach(PageElement::click);
    }

    public String getDefaultMergeStrategy() {
        return mergeConfig.find(By.className("default-merge-checked")).getAttribute("data-strategy-id");
    }

    public List<String> getEnabledMergeStrategies() {
        return mergeConfig.findAll(By.name("enabledIds")).stream()
                .filter(pageElement -> pageElement.getAttribute("checked") != null)
                .map(PageElement::getId)
                .collect(MoreCollectors.toImmutableList());
    }

    public List<String> getStrategiesWithDefaultLink() {
        return mergeConfig.findAll(By.className("default-merge-strategy")).stream()
                .filter(element -> element.isEnabled() && element.getAttribute("checked") == null)
                .map(PageElement::getValue)
                .collect(MoreCollectors.toImmutableList());
    }

    @Override
    public String getUrl() {
        return String.format("/projects/%s/repos/%s/settings/pull-requests", projectKey, slug);
    }

    public int getNumberOfRequiredApprovers() {
        if (requiredApprovers.isSelected()) {
            return Integer.parseInt(requiredApproversCount.getValue());
        } else {
            return 0;
        }
    }

    public void setDefaultMergeStrategy(String defaultId) {
        mergeConfig.findAll(By.className("default-merge-strategy-label")).stream()
                .filter(element -> defaultId.equals(element.getAttribute("data-strategy-id")))
                .forEach(PageElement::click);
    }

    public PullRequestRepositorySettingsPage setNumberOfRequiredApprovers(int n) {
        if (n == 0) {
            requiredApprovers.uncheck();
        } else {
            requiredApprovers.check();
            // clicking on the 'requiredApprovers' enables the 'requiredApproversCount' by Javascript,
            // so this makes sure there is no race conditions
            Poller.waitUntilTrue(requiredApproversCount.timed().isEnabled());
            PageElement option = requiredApproversCount.find(By.cssSelector(String.format("option[value='%d']", n)));
            if (!option.isPresent()) {
                throw new IllegalArgumentException("Unsupported number of approvers: " + n);
            } else {
                option.select();
            }
        }

        return this;
    }

    public PullRequestRepositorySettingsPage setRequireAllApprovals(boolean requireAllApprovals) {
        if (requireAllApprovals) {
            requireAllApprovalsCheckbox.check();
        } else {
            requireAllApprovalsCheckbox.uncheck();
        }

        return this;
    }

    public PullRequestRepositorySettingsPage setRequireTasksCompleted(boolean requireTasksCompleted) {
        if (requireTasksCompleted) {
            requireTasksCompletedCheckbox.check();
        } else {
            requireTasksCompletedCheckbox.uncheck();
        }

        return this;
    }

    public PullRequestRepositorySettingsPage clickSave() {
        scrollToBottom();
        waitForPageLoad(saveButton::click);
        return pageBinder.bind(PullRequestRepositorySettingsPage.class, projectKey, slug);
    }

    public RepositoryEditSettingsPage clickCancel() {
        waitForPageLoad(cancelLink::click);

        return pageBinder.bind(RepositoryEditSettingsPage.class, projectKey, slug);
    }
}
