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

import cz.moneta.test.harness.constants.HarnessConfigConstants;
import cz.moneta.test.harness.context.StoreAccessor;
import cz.moneta.test.harness.exception.HarnessException;
import org.apache.commons.lang3.tuple.Pair;
import org.openqa.selenium.By;
import org.openqa.selenium.Capabilities;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.edge.EdgeOptions;
import org.openqa.selenium.remote.DesiredCapabilities;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;

import static cz.moneta.test.harness.constants.HarnessConfigConstants.SELENIUM_DOWNLOAD_DIRECTORY;
import static cz.moneta.test.harness.constants.HarnessConfigConstants.SELENIUM_GRID_PLATFORM;

public class SeleniumEdgeConnector extends SeleniumWebConnector {

    public SeleniumEdgeConnector(Function<String, By> defaultLookup, StoreAccessor store) {
        super(defaultLookup, store);
    }

    @Override
    protected Pair<WebDriver, Boolean> getLocalWebDriver() {
        setupDriver();

        EdgeDriver driver = new EdgeDriver(getEdgeOptions());
        driver.manage()
                .window()
                .maximize();
        return Pair.of(driver, false);
    }

    private void setupDriver() {
        Optional.ofNullable(store.getConfig("selenium.edge.webdriver.path"))
                .map(path -> {
                    System.setProperty("webdriver.edge.driver", path);
                    return path;
                })
                .orElseThrow(() -> new AssertionError("Please provide path to the Edge driver using selenium.edge.webdriver.path configuration key or use a selenium grid"));
    }

    private EdgeOptions getEdgeOptions() {
        EdgeOptions edgeOptions = new EdgeOptions();

        this.driverUtils().addDefaultDesiredCapabilities(edgeOptions);

        Optional.ofNullable(store.getConfig("selenium.webdriver.edge.options"))
               .map(o -> o.split("\\s+"))
               .ifPresent(edgeOptions::addArguments);
        edgeOptions.addArguments(extraOptions);

        this.driverUtils().addAdditionalDesiredCapabilities(edgeOptions, "selenium.edge.capabilities");

        // Set up Selenium Grid session name
        edgeOptions.setCapability("se:name", store.get(HarnessConfigConstants.TEST_UNIQUE_ID).toString());

        // Choose which Selenium Grid node will be used
        Optional.ofNullable(store.getConfig(SELENIUM_GRID_PLATFORM))
                .ifPresent(platform -> edgeOptions.setPlatformName(platform));


        Map<String, Object> prefs = new HashMap<String, Object>();
        // Allow clipboard usage
        prefs.put("profile.default_content_setting_values.clipboard", 1);

        // Overrides default download directory in Edge profile preferences
        Optional.ofNullable(store.getConfig(SELENIUM_DOWNLOAD_DIRECTORY))
                .ifPresent(experimentalOptions -> {
                    prefs.put("download.default_directory", store.getConfig(SELENIUM_DOWNLOAD_DIRECTORY));
                });
        edgeOptions.setExperimentalOption("prefs", prefs);

        return edgeOptions;
    }

    @Override
    protected Capabilities getDesiredRemoteCapabilities() {
        return new DesiredCapabilities(getEdgeOptions());
    }

    @Override
    public void downloadFileViaIePrompt(int waitInSeconds) {
        throw new HarnessException("This method is not implemented on Chrome. Use capabilities settings instead.");
    }
}
