package ru.yandex.autotests.direct.web.pages.showcampbem.blocks.strategy;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.google.common.base.Preconditions;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;

import ru.yandex.autotests.direct.utils.strategy.objects.StrategyInfoWeb;
import ru.yandex.autotests.direct.web.data.strategy.cpm.CpmManualShowModeEnum;
import ru.yandex.autotests.direct.web.data.strategy.cpm.CpmStrategiesEnum;
import ru.yandex.autotests.direct.web.data.strategy.cpm.CpmStrategySpendMode;
import ru.yandex.autotests.direct.web.objects.strategies.cpm.CpmStrategyInfoWeb;
import ru.yandex.autotests.direct.web.util.DirectWebError;
import ru.yandex.autotests.direct.web.util.beanutils.BeanFieldsSetter;
import ru.yandex.autotests.direct.web.webelements.NumericInput;
import ru.yandex.autotests.direct.web.webelements.bem.CalendarReportWizardInputBEM;
import ru.yandex.autotests.direct.web.webelements.bem.CheckBoxBEM;
import ru.yandex.autotests.direct.web.webelements.bem.RadioBEM;
import ru.yandex.autotests.direct.web.webelements.bem.SelectBEM;
import ru.yandex.qatools.htmlelements.annotations.Name;
import ru.yandex.qatools.htmlelements.element.Button;

import static ch.lambdaj.Lambda.on;
import static ru.yandex.autotests.direct.web.data.strategy.cpm.CpmStrategySpendMode.BY_PERIOD;
import static ru.yandex.autotests.direct.web.util.WebElementsActions.fillTextInput;
import static ru.yandex.autotests.direct.web.util.WebElementsActions.getVisibleElement;
import static ru.yandex.autotests.direct.web.util.WebElementsActions.setCheckboxState;
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.beandiffer2.BeanDifferMatcher.beanDiffer;

public class CpmStrategyBlock extends StrategyBemBlock {

    //Ручная стратегия
    @Name("Чекбокс 'Дневной бюджет'")
    @FindBy(xpath = ".//span[contains(@data-bem, 'dayBudgetEnabled')]//input")
    private CheckBoxBEM isDayBudgetEnabled;

    @Name("Инпут 'Дневной бюджет'")
    @FindBy(xpath = ".//span[contains(@data-bem, 'sum')]//input")
    private NumericInput dayBudget;

    @Name("Селект: Режим показа")
    @FindBy(xpath = ".//span[contains(@data-bem, '\"name\":\"mode\",\"type\":\"select\"')]//select")
    private SelectBEM showMode;

    //Автоматические стратегии
    @Name("Радиокнопкпки 'Тратить'")
    @FindBy(xpath = ".//span[contains(@data-bem, 'spendMode')]//input")
    private List<RadioBEM> spendMode;

    @Name("Кнопка Календарь")
    @FindBy(xpath = ".//button[contains(@class,'b-date-range-picker__super-button')]")
    private List<Button> openCalendarButton;

    @Name("Календарь 'Период'")
    @FindBy(xpath = "//div[contains(@class,'super-calendar__untouch') and contains(@style,'visible')]")
    private List<CalendarReportWizardInputBEM> calendarInputBEM;

    @Name("Инпут 'Бюджет'")
    @FindBy(xpath = ".//span[contains(@data-bem, '\"name\":\"budget\"') or contains(@data-bem, '\"name\":\"weekBid\"')]//input")
    private List<NumericInput> budget;

    @Name("Чекбокс: 'Автопролонгация'")
    @FindBy(xpath = ".//div[contains(@class, 'b-strategy2-settings__control-wrap')]"
            + "//span[contains(@data-bem, 'autoProlongation')]")
    private List<CheckBoxBEM> autoProlongation;

    @Name("Инпут 'Средняя цена не более' за период")
    @FindBy(xpath = ".//span[contains(@data-bem, '\"name\":\"click')]//input")
    private List<NumericInput> middleCost;

    @Name("Кнопка 'Создать заново'")
    @FindBy(xpath = ".//button[contains(@class, 'b-strategy2-settings__recreate-period')]")
    private Button recreatePeriod;

    @Name("Настройки стратегии на период")
    @FindBy(xpath = ".//div[contains(@class, 'b-strategy2-settings__row_type_period-preview')]")
    private WebElement periodSettings;

    @Override
    public void fillStrategy(StrategyInfoWeb bean) {
        CpmStrategyInfoWeb strategy = (CpmStrategyInfoWeb) bean;
        newStrategyChooseBlock.selectStrategy(strategy.getStrategy().getValue());

        switch (strategy.getStrategy()) {
            case MANUAL:
                setCheckboxState(isDayBudgetEnabled, strategy.getDayBudgetEnabled());
                if (strategy.getDayBudget() != null) {
                    fillTextInput(dayBudget, strategy.getDayBudget().toString());
                }
                if (strategy.getShowMode() != null) {
                    showMode.selectByValue(strategy.getShowMode().getValue());
                }
                break;
            case MAX_REACH:
            case MAX_IMPRESSIONS:
                if (strategy.getSpendMode() != null) {
                    onSpendMode().selectByValue(strategy.getSpendMode().getValue());
                }
                if (strategy.getDateFrom() != null && strategy.getDateTo() != null) {
                    onOpenCalendarButton().click();
                    onCalendar().fillDate(strategy.getDateFrom(), strategy.getDateTo());
                }
                fillTextInput(onBudget(), strategy.getBudget().toString());
                if (strategy.getSpendMode() == BY_PERIOD) {
                    setCheckboxState(onAutoProlongation(), strategy.getAutoProlongation());
                }
                if (strategy.getMiddleCost() != null) {
                    fillTextInput(onMiddleCost(), strategy.getMiddleCost().toString());
                }
                break;
            default:
                throw new DirectWebError("Указана не поддерживаемая стратегия: " + strategy.getStrategy());
        }
    }

    @Override
    public void checkStrategy(StrategyInfoWeb expectedBean) {
        CpmStrategyInfoWeb expectedStrategy = (CpmStrategyInfoWeb) expectedBean;
        assertThat("стратегия соответствует ожиданию", getStrategy(expectedStrategy), beanDiffer(expectedStrategy));
    }

    public CpmStrategyInfoWeb getStrategy(CpmStrategyInfoWeb expectedBean) {
        Preconditions.checkArgument(expectedBean.getStrategy() != null, "Тип стратегии обязательное поле");
        CpmStrategyInfoWeb resultStrategy = new CpmStrategyInfoWeb();
        resultStrategy.setStrategy(getStrategyValue());
        if (resultStrategy.getStrategy() == CpmStrategiesEnum.MANUAL) {
            inAccordanceWith(expectedBean).forExisting(resultStrategy)
                    .set("dayBudgetEnabled", isDayBudgetEnabled, on(CheckBoxBEM.class).isSelected())
                    .set("dayBudget", this, on(CpmStrategyBlock.class).getDayBudgetValue())
                    .set("showMode", this, on(CpmStrategyBlock.class).getShowModeValue());
        } else if (expectedBean.getSpendMode() == BY_PERIOD) {
            resultStrategy.setSpendMode(BY_PERIOD);
            CpmStrategyInfoWeb actualSettings = getPeriodStrategySavedSettings();
            inAccordanceWith(expectedBean).forExisting(resultStrategy)
                    .set("budget", actualSettings, on(CpmStrategyInfoWeb.class).getBudget())
                    .set("middleCost", actualSettings, on(CpmStrategyInfoWeb.class).getMiddleCost())
                    .set("dateFrom", actualSettings, on(CpmStrategyInfoWeb.class).getDateFrom())
                    .set("autoProlongation", actualSettings, on(CpmStrategyInfoWeb.class).getAutoProlongation())
                    .set("dateTo", actualSettings, on(CpmStrategyInfoWeb.class).getDateTo());
        } else {
            BeanFieldsSetter<CpmStrategyInfoWeb> fieldsSetter =
                    inAccordanceWith(expectedBean).forExisting(resultStrategy)
                            .set("spendMode", this, on(CpmStrategyBlock.class).getSpendModeValue())
                            .set("budget", this, on(CpmStrategyBlock.class).getBudgetValue())
                            .set("middleCost", this, on(CpmStrategyBlock.class).getMiddleCostValue());
        }
        return resultStrategy;
    }

    private RadioBEM onSpendMode() {
        return getVisibleElement(spendMode);
    }

    private CalendarReportWizardInputBEM onCalendar() {
        return getVisibleElement(calendarInputBEM);
    }

    private NumericInput onBudget() {
        return getVisibleElement(budget);
    }

    private CheckBoxBEM onAutoProlongation() {
        return getVisibleElement(autoProlongation);
    }

    private NumericInput onMiddleCost() {
        return getVisibleElement(middleCost);
    }

    private Button onOpenCalendarButton() {
        return getVisibleElement(openCalendarButton);
    }

    public Double getBudgetValue() {
        return Double.parseDouble(onBudget().getValue());
    }

    public CpmStrategiesEnum getStrategyValue() {
        return CpmStrategiesEnum.deserializeFromString(newStrategyChooseBlock.getSelectedStrategy());
    }

    public Double getDayBudgetValue() {
        return Double.parseDouble(dayBudget.getValue());
    }

    public CpmManualShowModeEnum getShowModeValue() {
        return CpmManualShowModeEnum.deserializeFromString(showMode.getSelectedValue());
    }

    public CpmStrategySpendMode getSpendModeValue() {
        return CpmStrategySpendMode.deserializeFromString(onSpendMode().getSelectedValue());
    }

    public Double getMiddleCostValue() {
        return Double.parseDouble(onMiddleCost().getValue());
    }

    public CpmStrategyInfoWeb getPeriodStrategySavedSettings() {
        CpmStrategyInfoWeb strategy = new CpmStrategyInfoWeb();
        String settingsText = periodSettings.getText();
        Pattern datePattern = Pattern.compile("(\\d{2,4}\\.?){3}");
        SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy");
        Matcher dateMatcher = datePattern.matcher(settingsText);
        dateMatcher.find();
        int dateIdx;
        try {
            strategy.setDateFrom(dateFormat.parse(dateMatcher.group()));
            dateMatcher.find();
            strategy.setDateTo(dateFormat.parse(dateMatcher.group()));
            dateIdx = dateMatcher.end();
        } catch (ParseException e) {
            throw new DirectWebError("Ошибка при парсинге даты", e);
        }
        Pattern moneyPattern = Pattern.compile("\\b[\\d\\s]+\\.\\d+\\b");
        Matcher moneyMatcher = moneyPattern.matcher(settingsText);
        moneyMatcher.find(dateIdx);
        strategy.setBudget(Double.parseDouble(moneyMatcher.group().replaceAll("\\s", "")));
        moneyMatcher.find();
        strategy.setMiddleCost(Double.parseDouble(moneyMatcher.group().replaceAll("\\s", "")));
        strategy.setAutoProlongation(
                new CheckBoxBEM(
                        periodSettings.findElement(
                                By.xpath(".//span[contains(@data-bem, 'autoProlongation')]//input"))).isSelected());
        return strategy;
    }
}
