package com.atlassian.webdriver.bitbucket.element;

import com.atlassian.pageobjects.PageBinder;
import com.atlassian.pageobjects.binder.WaitUntil;
import com.atlassian.pageobjects.elements.PageElement;
import com.atlassian.pageobjects.elements.PageElementFinder;
import com.atlassian.pageobjects.elements.query.Poller;
import com.atlassian.webdriver.bitbucket.page.CommitListPage;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.google.inject.Inject;
import org.openqa.selenium.By;

import java.util.List;

public class BranchInfo {

    public static final Function<BranchInfoItem, String> TO_NAME = new Function<BranchInfoItem, String>() {
        @Override
        public String apply(BranchInfoItem input) {
            return input.getName();
        }
    };

    private final PageElement element;
    private final String projectKey;
    private final String repoSlug;

    @Inject
    private PageBinder pageBinder;

    @Inject
    private PageElementFinder elementFinder;

    public BranchInfo(PageElement element, String projectKey, String repoSlug) {
        this.element = element;
        this.projectKey = projectKey;
        this.repoSlug = repoSlug;
    }

    @WaitUntil
    protected void waitForLoad() {
        Poller.waitUntilTrue(element.timed().isPresent());
    }

    public BranchInfoItem getSingleBranch() {
        return pageBinder.bind(BranchInfoItem.class, element.find(By.className("branch-info-branch-single")), this);
    }

    public BranchInfoDialog showMultipleBranches() {
        element.find(By.className("branch-info-dropdown-trigger")).click();
        return pageBinder.bind(BranchInfoDialog.class, elementFinder.find(By.id("branch-info-dropdown")), this);
    }

    private CommitListPage openBranch(String branch) {
        return pageBinder.bind(CommitListPage.class, projectKey, repoSlug, branch);
    }

    public static class BranchInfoDialog {

        private final PageElement element;
        private final BranchInfo parent;

        @Inject
        private PageBinder pageBinder;

        public BranchInfoDialog(PageElement element, BranchInfo parent) {
            this.element = element;
            this.parent = parent;
        }

        @WaitUntil
        protected void waitForLoad() {
            Poller.waitUntilTrue(element.timed().isVisible());
        }

        public List<BranchInfoItem> getBranches() {
            return Lists.transform(element.findAll(By.className("branch-info-branch")), new Function<PageElement, BranchInfoItem>() {
                @Override
                public BranchInfoItem apply(PageElement input) {
                    return pageBinder.bind(BranchInfoItem.class, input, parent);
                }
            });
        }
    }

    public static class BranchInfoItem {

        private final PageElement element;
        private final BranchInfo parent;

        public BranchInfoItem(PageElement element, BranchInfo parent) {
            this.element = element;
            this.parent = parent;
        }

        public String getName() {
            return element.getText();
        }

        public CommitListPage click() {
            String branch = element.getText();
            element.click();
            return parent.openBranch(branch);
        }
    }

}
