package cz.moneta.test.harness.connectors.web;

import cz.moneta.test.harness.support.web.Lookup;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.Select;

import java.util.List;
import java.util.stream.Collectors;

public class Selects {

    private final SeleniumWebConnector connector;

    public Selects(SeleniumWebConnector connector) {
        this.connector = connector;
    }

    public void selectByVisibleText(String path, String text, Lookup lookup) {
        WebElement element = connector.waits()
                .waitForLazyElement(path, lookup);
        connector.scrolling().scrollIntoView(element);
        new Select(element).selectByVisibleText(text);
    }

    public void selectByValue(String path, String value, Lookup lookup) {
        WebElement element = connector.waits()
                .waitForLazyElement(path, lookup);
        connector.scrolling().scrollIntoView(element);
        connector.elementsActions().moveToElement(path, lookup);
        new Select(element).selectByValue(value);
    }

    public void selectByOptionOrder(String path, int optionOrder, Lookup lookup) {
        WebElement element = connector.waits()
                .waitForLazyElement(path, lookup);
        connector.scrolling().scrollIntoView(element);
        new Select(element).selectByIndex(--optionOrder);
    }

    /**
     * Select option by text part of option value
     * <p>
     * In some cases is necessary to select option only by part of value in option. This method accepts path to element
     * lookup strategy value and list of text parts of options.
     * </p>
     * <p>
     * In this method is created in xpath for select one value. Used strategy: create xpath with contains separated by
     * OR.
     * </p>
     * <p>
     * Example:
     * <pre>
     *         From ["ValueA", "ValueB"] will create xpath:
     *         "//option[contains(text(),'ValueA') or contains(text(),'ValueB')]"
     *     </pre>
     * </p>
     *
     * @param path             - path to select element
     * @param lookup           - lookup strategy for select element
     * @param textOptionsParts - list of option text parts to look for
     */
    public void selectByContainingTexts(String path, Lookup lookup, List<String> textOptionsParts) {
        List<String> optionXpaths = textOptionsParts.stream()
                .map(text -> String.format("contains(text(),'%s')", text))
                .collect(Collectors.toList());
        String joinedContains = String.join(" or ", optionXpaths);
        String optionXpath = String.format("//option[%s]", joinedContains);

        Waits waits = connector.waits();
        waits.waitForLazyElement(path, lookup)
                .findElements(waits.byLocator(Lookup.XPATH, optionXpath))
                .get(0)
                .click();
    }

    public String getFirstSelectedOptionText(String path, Lookup lookup) {
        Select select = new Select(connector.waits().waitForLazyElement(path, lookup));
        return select.getFirstSelectedOption().getText();
    }
}
