package com.intland.codebeamer.functionaltest.page;

import com.codeborne.selenide.Condition;
import com.codeborne.selenide.ex.UIAssertionError;
import com.google.common.base.Function;
import com.intland.codebeamer.functionaltest.page.admin.MembersPage;
import com.intland.codebeamer.functionaltest.page.common.EditorComponent;
import com.intland.codebeamer.functionaltest.page.common.IsPageLoaded;
import com.intland.codebeamer.functionaltest.page.mystart.MyStartPage;
import com.intland.codebeamer.functionaltest.page.projects.ProjectsPage;
import com.intland.codebeamer.functionaltest.page.systemadmin.SystemAdminPage;
import com.intland.codebeamer.functionaltest.page.trackers.AddAssociationDialog;
import com.intland.codebeamer.functionaltest.page.trackers.AddCommentDialog;
import com.intland.codebeamer.functionaltest.page.trackers.TrackersPage;
import com.intland.codebeamer.functionaltest.page.wiki.ProjectWikiPage;
import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.interactions.Actions;

import com.codeborne.selenide.SelenideElement;

import java.util.concurrent.TimeUnit;

import static com.codeborne.selenide.Condition.visible;
import static com.codeborne.selenide.Selectors.byTitle;
import static com.codeborne.selenide.Selenide.*;
import static com.codeborne.selenide.WebDriverRunner.getWebDriver;

public class BasePage implements IsPageLoaded {

    @Override
    public void waitForPageToLoad() {
        sleep(1000);
    }

    public boolean isPageLoaded() throws UnsupportedOperationException {
//        try {
//            Wait().withTimeout(5, TimeUnit.SECONDS)
//                    .ignoring(NoSuchElementException.class)
//                    .until(ExpectedConditions.visibilityOf($("#summary")));
//        }catch(Exception e){
//            return false;
//        }
//        return true;
        throw new UnsupportedOperationException("Override it");
    }

    public LoginPage clickOnLogout() {
        $(By.linkText("Logout")).click();
        return page(LoginPage.class);
    }

    public MyStartPage clickOnMyStartPage() {
        $(By.linkText("My Start")).click();
        return page(MyStartPage.class);
    }

    public ProjectsPage clickOnProjects() {
        $(By.linkText("Projects")).click();
        return page(ProjectsPage.class);
    }

    public ProjectWikiPage clickOnWiki() {
        $(By.linkText("Wiki")).click();
        return page(ProjectWikiPage.class);
    }

    public ReportsPage clickOnReports() {
        $(By.linkText("Reports")).click();
        return page(ReportsPage.class);
    }

    public TrackersPage clickOnTrackers() {
        $(By.linkText("Trackers")).click();
        TrackersPage trackersPage = page(TrackersPage.class);
        trackersPage.waitForPageToLoad();
        return trackersPage;
    }

    public ScmRepositoriesPage clickOnScmRepositories() {
        $(By.linkText("SCM Repositories")).click();
        $(By.linkText("New Repository")).waitUntil(visible, 60000);
        return page(ScmRepositoriesPage.class);
    }

    public BaselinesPage clickOnBaselines() {
        $(By.linkText("Baselines")).click();
        return page(BaselinesPage.class);
    }

    public ProjectAdminSettingsPage clickOnAdmin() {
        $(By.linkText("Admin")).click();
        return page(ProjectAdminSettingsPage.class);
    }

    public TrashPage clickOnTrash() {
        $(By.linkText("Trash")).click();
        return page(TrashPage.class);
    }

    public AboutPage clickOnAbout() {
        $(byTitle("About this installation")).click();
        return page(AboutPage.class);
    }

    public SystemAdminPage clickOnSystemAdmin() {
        $(By.linkText("System Admin")).click();
        return page(SystemAdminPage.class);
    }

    public void dragAndDrop(SelenideElement source, SelenideElement target) {
        Actions builder = new Actions(getWebDriver());
        source.shouldBe(visible);
        target.shouldBe(visible);
        builder.clickAndHold(source).moveToElement(target).release().build().perform();
    }

    public DocumentsPage clickOnDocuments() {
        $(By.partialLinkText("Documents")).click();
        return page(DocumentsPage.class);
    }

    public MembersPage clickOnAdminMembers() {
        Wait().withTimeout(10, TimeUnit.SECONDS)
                .pollingEvery(500, TimeUnit.SECONDS)
                .ignoring(NoSuchElementException.class)
                .ignoring(UIAssertionError.class)
                .until((Function<WebDriver, Boolean>) driver -> {
                    $(By.xpath(".//div[contains(@class, 'toolbar')]//a[text()='Admin']/following-sibling::img")).click();
                    sleep(500);
                    SelenideElement menu = $(By.xpath(".//div[@id='toolbarMenus']//a/span[text()='Members']"));
                    if (menu.isDisplayed()) {
                        menu.click();
                        return true;
                    }
                    return false;
                });
        return page(MembersPage.class);
    }

    public void checkIfAccessDenied(Condition condition) {
        $(By.xpath(".//div[@class='infoMessages']//*[contains(text(), 'Access Denied')]")).shouldBe(condition);
    }

    public void checkIfEvaluationWarning(Condition condition) {
        //starts at Trackers
        $(By.xpath(".//div[@class='warningtext' and contains(., 'Evaluation only')]")).shouldBe(condition);
        //ends at Trackers
    }

    public void checkIfSCMRepositories(Condition condition){
        $(By.linkText("SCM Repositories")).shouldBe(condition);
    }

    public void checkIfBaselines(Condition condition){
        $(By.linkText("Baselines")).shouldBe(condition);
    }

    public void checkIfDocuments(Condition condition){
        $(By.linkText("Documents")).shouldBe(condition);
    }

    public enum Hotkey {
        EDIT_SELECTED_ITEM(Keys.chord(Keys.ALT, "e"), EditorComponent.class),
        ADD_COMMENT_TO_SELECTED_ITEM(Keys.chord(Keys.ALT, "c"), AddCommentDialog.class),
        ADD_ASSOCIATION_TO_SELECTED_ITEM(Keys.chord(Keys.ALT, "l"), AddAssociationDialog.class);

        private final String text;
        public final Class<?> pageObjectClass;

        Hotkey(String s, Class<?> pageObjectClass) {
            text = s;
            this.pageObjectClass = pageObjectClass;
        }

        public boolean equalsName(String otherSelector) {
            return (otherSelector == null) ? false : text.equals(otherSelector);
        }

        public String toString() {
            return this.text;
        }
    }

    public Object sendHotkey(Hotkey hotkey) {
        $("body").sendKeys(hotkey.text);
        return hotkey.pageObjectClass != null ? page((Class<Object>) hotkey.pageObjectClass) : null;
    }

}
