package ru.yandex.autotests.direct.web.pages.regionselectpopup;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.apache.commons.collections4.CollectionUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;

import ru.yandex.autotests.direct.web.util.DirectWebError;
import ru.yandex.autotests.direct.web.util.helpers.TreeHelper;
import ru.yandex.autotests.direct.web.webelements.bem.CheckBoxBEM;
import ru.yandex.autotests.direct.web.webelements.bem.TumblerBEM;
import ru.yandex.qatools.htmlelements.annotations.Name;
import ru.yandex.qatools.htmlelements.element.Button;
import ru.yandex.qatools.htmlelements.element.HtmlElement;
import ru.yandex.qatools.htmlelements.loader.HtmlElementLoader;

import static java.lang.String.format;
import static ru.yandex.autotests.direct.web.data.contactinfo.Regions.EMPTY;

@FindBy(xpath = "//div[contains(@class, 'popup__content')][.//div/div[contains(@class, 'b-regions')]]")
@Name("Поп-ап изменения Единый регион показа для всех объявлений")
public class RegionSelectPopupBlockBEM extends HtmlElement {

    @Name("Кнопка 'Ок' или 'Сохранить'")
    @FindBy(xpath = ".//button[contains(@class, 'b-edit-regions-popup__save')]")
    public Button saveButton;

    @Name("Кнопка 'Отмена'")
    @FindBy(xpath = ".//button[contains(@class, 'b-edit-regions-popup__cancel')]")
    public Button cancelButton;

    @Name("Сбросить выбранные регионы")
    @FindBy(xpath = ".//span[contains(@class, 'reset-selected')]")
    public WebElement clearAllRegionsLink;

    @Name("Список открытых чекбоксов")
    @FindBy(xpath = ".//span[contains(@class, 'checkbox_js_inited')]/span")
    public List<CheckBoxBEM> checkBoxBEMList;

    @Name("Список открытых чекбоксов")
    @FindBy(css = ".checkbox_js_inited.checkbox_checked_yes")
    public List<CheckBoxBEM> selectedCheckBoxBEMList;

    private GeoCorrectionsPopupBlock geoCorrectionsPopupBlock;

    @Name("Блок ошибок валидации")
    @FindBy(xpath = ".//div[contains(@class, 'b-edit-regions-popup__errors')]")
    public WebElement regionsPopupErrorsBlock;

    @Name("Тумблер корректировок ставок по гео")
    @FindBy(xpath = ".//span[contains(@class,'b-regions__bids-corrections-mode-switcher')]//input")
    private TumblerBEM tumblerGeoBidsCorrections;

    @Name("Кнопка 'очистить корректировки'")
    @FindBy(xpath = ".//span[contains(@class, 'b-regions__reset-bids')]")
    private WebElement clearGeoBidsCorrections;

    private TreeHelper regionsTree;

    public void clickOnCancelButton() {
        cancelButton.click();
    }

    public void clickOnSaveButton() {
        saveButton.click();
    }

    public void fillRegions(String geo) {
        if (geo == null) {
            return;
        } else if (geo.equals(EMPTY.getRegionID())) {
            clearAllRegions();
        } else {
            selectRegions(geo);
        }
        saveButton.click();
    }

    public void fillRegions(List<String> geo) {
        fillRegions(CollectionUtils.emptyIfNull(geo).stream().collect(Collectors.joining(",")));
    }

    public void clearAllRegions() {
        clearAllRegionsLink.click();
    }

    public WebElement getRegionsPopupErrorsBlock() {
        return regionsPopupErrorsBlock;
    }


    public RegionLineBlockBEM getRegionSelect(String regionId) {
        List<WebElement> elements = findElements(
                By.xpath(format(".//div[contains(@class,'b-regions-tree__region_id_%s ')]", regionId)));
        if (elements.isEmpty()) {
            throw new DirectWebError("don't find region id=" + regionId);
        }
        return HtmlElementLoader.createHtmlElement(RegionLineBlockBEM.class, elements.get(0), "строчка региона");
    }

    public List<String> getSelectedRegions() {
        return selectedCheckBoxBEMList.stream()
                .map(x -> x.getWrappedElement().findElement(By.xpath(".//input")))
                .map(x -> x.getAttribute("id").replace("region-", ""))
                .collect(Collectors.toList());
    }

    public void openRegionCorrectionPopup(String regionId) {
        expandAll(regionId);
        getRegionSelect(regionId).openBidCorrection();
    }

    public void setTumbler(Boolean status) {
        tumblerGeoBidsCorrections.set(status);
    }

    public void clearAllGeoCorrections() {
        clearGeoBidsCorrections.click();
    }

    private void selectRegions(String geo) {
        //Обходим список в обратном лексографическом порядке, что бы сначала выствили все плюс регионы, а только потом минус
        Stream.of(geo.split(","))
                .sorted(Collections.reverseOrder())
                .forEach(this::selectRegion);
    }

    private void selectRegion(String regionID) {
        RegionLineBlockBEM region = getRegionSelect(regionID.replace("-", ""));
        expandAll(regionID);
        if (regionID.startsWith("-")) {
            region.deselect();
        } else {
            region.select();
        }
    }

    //для отображения regionSelect раскрываем все регионы в дереве от корня до текущего
    private void expandAll(String regionId) {
        getRegionsTree().getAncestorsFor(regionId).forEach(id -> getRegionSelect(id).expand());
    }

    private TreeHelper getRegionsTree() {
        if (regionsTree == null) {
            HashMap<String, String> treeMap = new HashMap<>();
            String dataBemJson = findElement(By.xpath(".//div[contains(@data-bem, 'b-regions-tree')]"))
                    .getAttribute("data-bem");

            JsonObject dataBem = new JsonParser().parse(dataBemJson).getAsJsonObject();
            // Раскладываем древо в map, ключ-потомок, значение-родитель
            dataBem.getAsJsonObject("b-regions-tree")
                    .getAsJsonObject("roots")
                    .entrySet()
                    .forEach(x ->
                            x.getValue().getAsJsonObject().getAsJsonArray("inners").forEach(
                                    y -> treeMap.put(y.getAsString(), x.getKey())));

            regionsTree = new TreeHelper(treeMap);
        }
        return regionsTree;
    }
}
