package ru.yandex.autotests.direct.web.pages.banners.blocks.edit.bem;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;

import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;

import ru.yandex.autotests.direct.utils.config.DirectTestRunProperties;
import ru.yandex.autotests.direct.web.objects.banners.BannerPhraseInfoWeb;
import ru.yandex.autotests.direct.web.objects.banners.McBannerInfoWeb;
import ru.yandex.autotests.direct.web.objects.groups.McGroupInfoWeb;
import ru.yandex.autotests.direct.web.util.JavaScriptActions;
import ru.yandex.autotests.direct.web.util.testinterfaces.IWebFrom;
import ru.yandex.qatools.htmlelements.annotations.Name;
import ru.yandex.qatools.htmlelements.element.Button;
import ru.yandex.qatools.htmlelements.element.TextInput;
import ru.yandex.qatools.htmlelements.matchers.WebElementMatchers;

import static ch.lambdaj.Lambda.on;
import static java.lang.Long.parseLong;
import static java.util.Objects.isNull;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.core.IsEqual.equalTo;
import static ru.yandex.autotests.direct.web.util.OperationSystemUtils.sleep;
import static ru.yandex.autotests.direct.web.util.WebElementsActions.fillTextInput;
import static ru.yandex.autotests.direct.web.util.beanutils.BeanFieldsSetter.inAccordanceWith;
import static ru.yandex.autotests.irt.testutils.allure.TestSteps.assertThat;
import static ru.yandex.autotests.irt.testutils.allure.TestSteps.assumeThat;
import static ru.yandex.autotests.irt.testutils.beandiffer2.BeanDifferMatcher.beanDiffer;
import static ru.yandex.qatools.htmlelements.matchers.MatcherDecorators.should;
import static ru.yandex.qatools.htmlelements.matchers.MatcherDecorators.timeoutHasExpired;

@FindBy(xpath = ".//div[contains(@class, 'b-edit-group ')]")
public class EditGroupWithMcBannerBlockBem extends EditGroupWithBannerBlockBEMBase implements IWebFrom<McGroupInfoWeb> {

    @Name("Задать метки")
    @FindBy(xpath = ".//button[contains(@class, 'b-group-tags2__switcher')]")
    private Button setTagsButton;

    @Name("Инпут 'Название группы'")
    @FindBy(xpath = ".//span[contains(@class, 'name-input')]//input")
    private TextInput groupName;

    @Name("Кнопка 'Добавить объявление'")
    @FindBy(xpath = ".//button[contains(@class, 'b-edit-banner-add2__add-button')]")
    private Button addBannerButton;

    @Name("Иконки удаления слов")
    @FindBy(xpath = ".//span[contains(@class, 'b-group-edit-phrase__remove')]")
    private List<WebElement> removeWordsButton;

    private List<McBannerBlockBem> banners;

    public Long getAdGroupId() {
        return parseLong(getAdGroupId(this.getAttribute("data-bem")));
    }

    public String getAdGroupName() {
        return groupName.getText();
    }

    public List<McBannerInfoWeb> getBanners(List<McBannerInfoWeb> expectedBeans) {
        List<McBannerInfoWeb> result = new ArrayList<>();
        int minSize = Math.min(expectedBeans.size(), banners.size());
        for (int i = 0; i < minSize; i++) {
            result.add(banners.get(i).getFormFieldsAccording(expectedBeans.get(i)));
        }
        while (expectedBeans.size() > minSize) {
            result.add(new McBannerInfoWeb());
            minSize++;
        }
        while (banners.size() > minSize) {
            McBannerBlockBem currentBlock = banners.get(minSize - 1);
            result.add(
                    new McBannerInfoWeb()
                            .withBannerId(currentBlock.getBannerId())
                            .withHref(currentBlock.getHref())
                            .withImageAd(currentBlock.getImageAd()));
            minSize++;
        }
        return result;
    }

    @Override
    public void fillParameters(McGroupInfoWeb bean) {
        fillGroupName(bean.getAdGroupName());
        fillBanners(bean.getBanners());
        fillPhrases(bean.getPhrases());
        fillMinusKeyWordsAndExpectSuccess(bean.getMinusKeywords());
        fillRegions(bean.getGeo());
        fillMaxClickPrice(bean.getMaxClickPrice());
        fillHierarchicalMultipliers(bean.getHierarchicalMultipliersWeb());
        fillTags(bean.getTags());
    }

    public void fillGroupName(String name) {
        if (name == null) {
            return;
        }
        fillTextInput(groupName, name);
        new JavaScriptActions(config).fireKeyUpEvent(groupName.getWrappedElement());
    }

    @Override
    protected void fillPhrases(BannerPhraseInfoWeb[] phrases) {
        if (phrases == null) {
            return;
        }
        super.fillPhrases(phrases);
        sleep(1000);
        removeWordsButton.forEach(WebElement::click);
    }

    private void fillBanners(List<McBannerInfoWeb> beans) {
        if (isNull(beans)) {
            return;
        }
        for (int i = 0; i < beans.size(); i++) {
            if (i == banners.size()) {
                addNewBannerToGroup(beans.get(i));
            } else {
                editBanner(beans.get(i), i);
            }
        }
    }

    @Override
    public void checkParameters(McGroupInfoWeb expectedBean) {
        assertThat("параметры группы соответствуют ожиданию", getFormFieldsAccording(expectedBean),
                beanDiffer(expectedBean));
    }

    @Override
    public McGroupInfoWeb getFormFieldsAccording(McGroupInfoWeb expectedBean) {
        return inAccordanceWith(expectedBean).forNew(McGroupInfoWeb.class)
                .set("adGroupName", this, on(EditGroupWithMcBannerBlockBem.class).getAdGroupName())
                .set("adGroupId", this, on(EditGroupWithMcBannerBlockBem.class).getAdGroupId())
                .set("banners", this, on(EditGroupWithMcBannerBlockBem.class)
                        .getBanners(expectedBean.getBanners()))
                .set("phrases", this, on(EditGroupWithMcBannerBlockBem.class).getPhrasesBeans())
                .set("minusKeywords", this,
                        on(EditGroupWithMcBannerBlockBem.class).getMinusKeywords().stream().toArray(String[]::new))
                .set("geo", this, on(EditGroupWithMcBannerBlockBem.class).getRegionIDs())
                .set("hierarchicalMultipliersWeb", this, on(EditGroupWithMcBannerBlockBem.class)
                        .getHierarchicalMultipliersAccording(expectedBean.getHierarchicalMultipliersWeb()))
                .set("tags", this, on(EditGroupWithMcBannerBlockBem.class).getTags())
                .set("maxClickPrice", this, on(EditGroupWithMcBannerBlockBem.class).getMaxClickPriceValue())
                .getActualBean();
    }

    public BannerPhraseInfoWeb[] getPhrasesBeans() {
        return Stream.of(getPhrases()).map(x -> new BannerPhraseInfoWeb().withPhrase(x))
                .toArray(BannerPhraseInfoWeb[]::new);
    }


    public void addNewBannerToGroup(McBannerInfoWeb bannerInfoWeb) {
        int oldSize = banners.size();
        addBannerButton.click();
        assumeThat("добавлен новый баннер", banners.size(), equalTo(oldSize + 1));
        editBanner(bannerInfoWeb, oldSize);
    }

    public void editBanner(McBannerInfoWeb bannerInfoWeb, int index) {
        McBannerBlockBem bannerBlockBem = banners.get(index);
        bannerBlockBem.setConfig(config);
        bannerBlockBem.fillParameters(bannerInfoWeb);
    }

    @Override
    protected void fillTags(List<String> tags) {
        if (tags == null) {
            return;
        }
        setTagsButton.click();
        tagsPopup.deselectAllTags();
        tagsPopup.fillTagsTextInput(tags);
        tagsPopup.clickOnSaveButton();
        assumeThat("попап меток исчез", tagsPopup, should(not(WebElementMatchers.isDisplayed()))
                .whileWaitingUntil(timeoutHasExpired(TimeUnit.SECONDS.toMillis(
                        DirectTestRunProperties.getInstance().getDirectWebWebdriverImplicityWaitTimeoutSec()))));
    }
}
