package be.iminds.ilabt.jfed.connectivity_tester;

import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.commons.configuration.XMLConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.inject.Inject;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * User: twalcari
 * Date: 1/6/14
 * Time: 10:20 AM
 */
public class ConnectivityTestSuite {
    private static final Logger LOG = LoggerFactory.getLogger(ConnectivityTestSuite.class);
    private static final String TYPE_STRING = "string", TYPE_INT = "int", TYPE_BOOLEAN = "boolean";
    private final List<ConnectivityTest> tests;

    private final ConnectivityTestFactory connectivityTestFactory;
    private final AMConnectionTestGenerator amConnectionTestGenerator;
    private final ProxyTestGenerator proxyTestGenerator;


    @Inject
    public ConnectivityTestSuite(ConnectivityTestFactory connectivityTestFactory,
                                 AMConnectionTestGenerator amConnectionTestGenerator,
                                 ProxyTestGenerator proxyTestGenerator) {
        this.connectivityTestFactory = connectivityTestFactory;
        this.amConnectionTestGenerator = amConnectionTestGenerator;
        this.proxyTestGenerator = proxyTestGenerator;

        tests = new ArrayList<>();

        try {
            XMLConfiguration config = new XMLConfiguration(DoTests.class.getResource("/tests.xml"));
            config.setThrowExceptionOnMissing(true);
            for (HierarchicalConfiguration testConf : config.configurationsAt("test")) {

                String testType = testConf.getString("type");

                ConnectivityTest test = null;

                switch (testType) {
                    case "hasIPv4": {
                        test = connectivityTestFactory.createHasIPv4AddressTest();
                        break;
                    }
                    case "hasIPv6": {
                        test = connectivityTestFactory.createHasIPv6AddressTest();
                        break;
                    }
                    case "resolveIPv4": {
                        String address = testConf.getString("address");
                        boolean useAlternativeDns = testConf.getBoolean("useAlternativeDns");
                        String expectedAddress = testConf.getString("expectedAddress", null);

                        if (expectedAddress != null)

                            test = new Resolve4Test(address, useAlternativeDns, expectedAddress);
                        else
                            test = new Resolve4Test(address, useAlternativeDns);
                        break;
                    }
                    case "resolveIPv6": {
                        String address = testConf.getString("address");
                        boolean useAlternativeDns = testConf.getBoolean("useAlternativeDns");
                        String expectedAddress = testConf.getString("expectedAddress", null);

                        if (expectedAddress != null)

                            test = new Resolve6Test(address, useAlternativeDns, expectedAddress);
                        else
                            test = new Resolve6Test(address, useAlternativeDns);
                        break;
                    }
                    case "pingIPv4": {
                        String address = testConf.getString("address");
                        test = new Ping4Test(address);
                        break;
                    }
                    case "pingIPv6": {
                        String address = testConf.getString("address");
                        test = new Ping6Test(address);
                        break;
                    }
                    case "HostAndPort": {
                        String hostname = testConf.getString("hostname");
                        int port = testConf.getInt("port");
                        String description = testConf.getString("description");
                        String category = testConf.getString("category");
                        test = new HostAndPortTest(hostname, port, description, category);
                        break;
                    }

                    case "SslHostAndPort": {
                        String hostname = testConf.getString("hostname");
                        int port = testConf.getInt("port");
                        String description = testConf.getString("description");
                        String category = testConf.getString("category");
                        test =
                                connectivityTestFactory.createSslHostAndPortTest(hostname, port, description, category);
                        break;
                    }
                    case "GetSACredential": {
                        test = connectivityTestFactory.createGetSACredentialTest();
                        break;
                    }
                    case "GetVersion": {
                        String authUrn = testConf.getString("authUrn");
                        test = connectivityTestFactory.createGetVersionTest(authUrn);
                        break;
                    }
                    default:
                        throw new IllegalArgumentException("Unknown test type: " + testType);

                }

                tests.add(test);
            }

//                } catch (ClassNotFoundException | NoSuchMethodException
//                        | InstantiationException | IllegalAccessException
//                        | InvocationTargetException e) {
//                    LOG.error("Error while instantiating test " + testConf.getString("@id") + ". Skipping.", e);
//                }
//            }


        } catch (ConfigurationException e) {
            LOG.error("Error while loading connectivity tests", e);
        }
        tests.addAll(amConnectionTestGenerator.generateTests());
        tests.addAll(proxyTestGenerator.generateTests());
    }

    public List<ConnectivityTest> getTests() {
        return Collections.unmodifiableList(tests);
    }

}
