package com.intland.codebeamer.functionaltest.page.trackers;

import com.codeborne.selenide.Condition;
import com.codeborne.selenide.ElementsCollection;
import com.codeborne.selenide.SelenideElement;
import com.codeborne.selenide.ex.UIAssertionError;
import com.google.common.base.Function;
import com.intland.codebeamer.functionaltest.page.BasePage;
import com.intland.codebeamer.functionaltest.page.SubmitWorkItemPage;
import com.intland.codebeamer.functionaltest.page.common.IsPageLoaded;
import com.intland.codebeamer.functionaltest.page.common.MoreMenuHelper;


import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;

import java.util.concurrent.TimeUnit;

import static com.codeborne.selenide.Selenide.*;
import static com.codeborne.selenide.Condition.text;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;

public class TrackerItemDetailsPage extends BasePage {

    public AssociationTab associationTab = new AssociationTab();

    private SelenideElement moreMenuLink = $(By.xpath(".//a[text()='more']/following-sibling::img"));


    public enum TabType {
        COMMENTS_ATTACHMENTS("Comments & Attachments", CommentsTab.class),
        ASSOCIATIONS("Associations", AssociationTab.class),
        CHILDREN("Children", null);

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

        TabType(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 CreateEditTrackerItemPage clickOnNewItem() {
        $(By.linkText("New Item")).click();
        return page(CreateEditTrackerItemPage.class);
    }

    public SubmitWorkItemPage clickOnNewTestRun() {
        $(By.linkText("New Test Run")).click();
        return page(SubmitWorkItemPage.class);
    }

    public void clickOnTransitionInStatusContextMenu(String transitionName) {
        $(By.className("propertyTable")).$(By.className("menuArrowDown")).click();
        $(By.className("propertyTable")).$(By.partialLinkText(transitionName)).click();
    }

    public void assertThatFieldHasValue(String fieldName, String value) {
    	if (fieldName.equals("Summary")) {
    		$(By.className("breadcrumbs-summary")).$(By.tagName("a")).shouldHave(text(value));
    	} else {
    		ElementsCollection tds = $(By.className("propertyTable")).$$(By.tagName("td"));
    		for (int i = 0; i < tds.size(); i++) {
    			if (tds.get(i).getText().equals(fieldName + ":")) {
    				String propertyValueHtml = tds.get(i + 1).getText();
    				// System.out.println("propertyValueHtml: <" + propertyValueHtml + ">");
    				// System.out.println("value: <" + value + ">");
    				assertTrue(propertyValueHtml.contains(value));
    				break;
    			}
    		}
    	}
    }

    public void assertThatFieldHasNoValue(String fieldName, String value) {
        ElementsCollection tds = $(By.className("propertyTable")).$$(By.tagName("td"));
        for (int i = 0; i < tds.size(); i++) {
            if (tds.get(i).getText().equals(fieldName + ":")) {
                String propertyValueHtml = tds.get(i + 1).getText();
                // System.out.println("propertyValueHtml: <" + propertyValueHtml + ">");
                // System.out.println("value: <" + value + ">");
                assertFalse(propertyValueHtml.contains(value));
                break;
            }
        }
    }

    public BasePage clickOnTab(TabType tabType) {
        $(By.xpath(".//div[@id='task-details']/div[@class='ditch-tab-wrap']//div[contains(., '" + tabType.text + "')]")).click();
        return tabType.pageObjectClass != null ? page((Class<BasePage>) tabType.pageObjectClass) : null;
    }

    public String getBusinessValue() {
        return $(By.xpath(".//td[text()='Business Value:']/following-sibling::td[@class='tableItem']")).getText();
    }

    public boolean isPageLoaded() throws UnsupportedOperationException {
        return $(".propertyTable").should(Condition.exist).exists();
    }

    public IsPageLoaded clickOnMoreMenuItem(MoreMenuHelper.MoreMenuItem moreMenuItem) {
       return MoreMenuHelper.clickOnMoreMenuItem(moreMenuItem);
    }

    public void checkIfMoreMenuItem (MoreMenuHelper.MoreMenuItem moreMenuItem, Condition condition) {
        MoreMenuHelper.checkIfMoreMenuItem(moreMenuItem, condition);
    }

    public void checkIfGenerateRisk(Condition condition) {
        $(By.xpath(".//a[text()='Generate Risk']")).shouldBe(condition);
    }

    public void checkIfEdit(Condition condition) {
        $(By.xpath(".//a[@text()='Edit']")).shouldBe(condition);
    }

    public class EditAssociationModal implements IsPageLoaded {

        @Override
        public void waitForPageToLoad() {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean isPageLoaded() throws UnsupportedOperationException {
            return false;
        }
    }

    public static class AssociationTab extends BasePage {

        public enum ContextMenuItem {
            EDIT("Edit", EditAssociationModal.class),
            DELETE("Delete...", null);

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

            ContextMenuItem(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 IsPageLoaded clickOnContextMenuItemOfItem(String itemLabel, int index, AddAssociationDialog.AssociationType associationType, ContextMenuItem contextMenuItem) {
            Wait().withTimeout(10, TimeUnit.SECONDS)
                    .pollingEvery(1, TimeUnit.SECONDS)
                    .ignoring(NoSuchElementException.class)
                    .ignoring(UIAssertionError.class)
                    .until((Function<WebDriver, Boolean>) driver -> {
                        //click on context menu arrow of the wanted row
                        SelenideElement row = $(By.xpath("(.//div[@id='task-details-associations']/table/tbody/tr[.//a[contains(., '" + itemLabel + "')] and .//td[contains(., '" + associationType + "')]])[" + index + "]"));
                        row.hover();
                        row.find(By.xpath(".//img[@class='menuArrowDown']")).hover().click();
                        $(By.xpath(".//div[normalize-space(@class)='yuimenu' and contains(@style,'display: block')]//a[contains(text(), '" + contextMenuItem.text + "')]")).click();
                        return true;
                    });

            return contextMenuItem.pageObjectClass != null ? page((Class<? extends IsPageLoaded>) contextMenuItem.pageObjectClass) : null;
        }
    }

    public static class CommentsTab extends BasePage {

        public enum ContextMenuItem {
            EDIT("Edit", AddCommentDialog.class),
            DELETE("Delete...", null);

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

            ContextMenuItem(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 IsPageLoaded clickOnContextMenuItemOfComment(String comment, int index, CommentsTab.ContextMenuItem contextMenuItem) {

            Wait().withTimeout(10, TimeUnit.SECONDS)
                    .pollingEvery(1, TimeUnit.SECONDS)
                    .ignoring(NoSuchElementException.class)
                    .ignoring(UIAssertionError.class)
                    .until((Function<WebDriver, Boolean>) driver -> {
                        //click on context menu arrow of the wanted row
                        SelenideElement row = $(By.xpath("(.//div[@id='task-details-attachments']/table/tbody/tr[.//span[contains(., '" + comment + "')]])[" + index + "]"));
                        row.hover();
                        row.find(By.xpath(".//img[@class='menuArrowDown']")).hover().click();
                        $(By.xpath(".//div[normalize-space(@class)='yuimenu' and contains(@style,'display: block')]//a[contains(text(), '" + contextMenuItem.text + "')]")).click();
                        return true;
                    });


            return contextMenuItem.pageObjectClass != null ? page((Class<? extends IsPageLoaded>) contextMenuItem.pageObjectClass) : null;
        }


    }
}
