package be.iminds.ilabt.jfed;

import be.iminds.ilabt.jfed.lowlevel.*;

import be.iminds.ilabt.jfed.fedmon.webapi.service.json.*;
import be.iminds.ilabt.jfed.util.GeniUrn;
import be.iminds.ilabt.jfed.util.JFedTrustStore;
import be.iminds.ilabt.jfed.util.KeyUtil;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;

import javax.annotation.Nullable;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;

/**
 * User: twalcari
 * Date: 1/13/2015
 * Time: 11:40
 */
public class TestAuthoritiesModule extends AbstractModule {
    public static final String hrnA = "Example auth with user for testing";
    public static final String urlA_am2 = "https://am."+TestCertHelper.authority1Hostname+"/2.0";
    public static final String urlA_am3 = "https://am."+TestCertHelper.authority1Hostname+"/3.0";
    public static final String urlA_pgSa1 = "https://sa."+TestCertHelper.authority1Hostname+"/";

    public static final String hrnB = "Example 2nd auth for testing";
    public static final String urlB_am2 = "https://am."+TestCertHelper.authority2Hostname+"/2.0";
    public static final String urlB_am3 = "https://am."+TestCertHelper.authority2Hostname+"/3.0";
    public static final String urlB_pgSa1 = "https://sa."+TestCertHelper.authority2Hostname+"/";

    public static final String hrnC = "Example SCS for testing";
    public static final String urlC_scs = "https://scs."+TestCertHelper.authority3Hostname+"/scs";

    public static final String hrnFake = "Fake Authority for testing ... fake authorities";

    public static final String urlC_am2 = "https://am."+TestCertHelper.authority3Hostname+"/am/2.0";
    public static final String urlC_am3 = "https://am."+TestCertHelper.authority3Hostname+"/am/3.0";

    public static class AMConfig {
        private final boolean hasV2;
        private final boolean hasV3;
        private final boolean hasUpToDateAdv;
        private final boolean hasAny;

        public AMConfig() {
            this(false, true, false, true);
        }
        public AMConfig(boolean hasV2, boolean hasV3, boolean hasUpToDateAdv, boolean hasAny) {
            this.hasV2 = hasV2;
            this.hasV3 = hasV3;
            this.hasUpToDateAdv = hasUpToDateAdv;
            this.hasAny = hasAny;
        }
    }

    private final AMConfig am1conf;
    private final AMConfig am2conf;
    private final AMConfig am3conf;

    public TestAuthoritiesModule() {
        this(new AMConfig(), new TestAuthoritiesModule.AMConfig(true/*hasV2*/, false/*hasV3*/, false/*hasUpToDateAdv*/, false/*hasAny*/), new AMConfig());
    }
    public TestAuthoritiesModule(AMConfig am1conf, AMConfig am2conf, AMConfig am3conf) {
        this.am1conf = am1conf;
        this.am2conf = am2conf;
        this.am3conf = am3conf;
    }

    @Override
    protected void configure() {
//        bind(File.class).annotatedWith(Names.named("authoritiesFile")).toInstance(authoritiesFile);
    }

    @Provides
    private TestbedInfoSource provideTestbedInfoSource(JFedTrustStore trustStore, TestCertHelper testCertHelper) throws MalformedURLException, JFedException {
        List<TestbedBuilder> testbedBuilders = new ArrayList<TestbedBuilder>();

        int serviceId = 100;

        TestbedBuilder testbedBuilder;
        ServerBuilder serverBuilder;
        ServiceBuilder serviceBuilder;

        testbedBuilder = new TestbedBuilder();
        serverBuilder = new ServerBuilder();
        testbedBuilder.setId("test1");
        serverBuilder.setId(1);
        testbedBuilder.addServerBuilder(serverBuilder);
        testbedBuilder.setLongName(hrnA);
        serverBuilder.setName(hrnA);
        testbedBuilder.setDefaultComponentManagerUrn(TestCertHelper.am1Urn);
        serverBuilder.setDefaultComponentManagerUrn(TestCertHelper.am1Urn);
        serverBuilder.setServerType("test");
        serverBuilder.setCertificateChain(KeyUtil.x509certificateToPem(testCertHelper.authority1Cert));
        if (am1conf.hasAny) serverBuilder.addFlag(Server.Flag.featureStitchingAny);
        if (am1conf.hasUpToDateAdv) serverBuilder.addFlag(Server.Flag.featureStitchingAdvertisementRspecUptodate);
        serverBuilder.addFlag(Server.Flag.workaroundAddExpiresAttributeToRequestRspec);

        if (am1conf.hasV2) {
            serviceBuilder = new ServiceBuilder();
            serverBuilder.addServiceBuilder(serviceBuilder);
            serviceBuilder.setUrn(TestCertHelper.am1Urn);
            serviceBuilder.setUrl(urlA_am2);
            serviceBuilder.setApi(ApiInfo.ApiName.GENI_AM.getId());
            serviceBuilder.setApiVersion("2");
            serviceBuilder.setId(serviceId++);
        }

        if (am1conf.hasV3) {
            serviceBuilder = new ServiceBuilder();
            serverBuilder.addServiceBuilder(serviceBuilder);
            serviceBuilder.setUrn(TestCertHelper.am1Urn);
            serviceBuilder.setUrl(urlA_am3);
            serviceBuilder.setApi(ApiInfo.ApiName.GENI_AM.getId());
            serviceBuilder.setApiVersion("3");
            serviceBuilder.setId(serviceId++);
        }

        if (true) {
            serviceBuilder = new ServiceBuilder();
            serverBuilder.addServiceBuilder(serviceBuilder);
            serviceBuilder.setUrn(TestCertHelper.saUrn);
            serviceBuilder.setUrl(urlA_pgSa1);
            serviceBuilder.setApi(ApiInfo.ApiName.PROTOGENI_SA.getId());
            serviceBuilder.setApiVersion("1");
            serviceBuilder.setId(serviceId++);
        }

        serverBuilder.setUrnTld(GeniUrn.parse(serverBuilder.getDefaultComponentManagerUrn()).getEncodedTopLevelAuthority());
        serverBuilder.setBaseUrl(serverBuilder.getServiceBuilders().get(0).getUrl());

        testbedBuilders.add(testbedBuilder);





        testbedBuilder = new TestbedBuilder();
        serverBuilder = new ServerBuilder();
        testbedBuilder.setId("test2");
        serverBuilder.setId(2);
        testbedBuilder.addServerBuilder(serverBuilder);
        testbedBuilder.setLongName(hrnB);
        serverBuilder.setName(hrnB);
        testbedBuilder.setDefaultComponentManagerUrn(TestCertHelper.am2Urn);
        serverBuilder.setDefaultComponentManagerUrn(TestCertHelper.am2Urn);
        serverBuilder.setServerType("test");
        serverBuilder.setCertificateChain(KeyUtil.x509certificateToPem(testCertHelper.authority2Cert));
        if (am2conf.hasAny) serverBuilder.addFlag(Server.Flag.featureStitchingAny);
        if (am2conf.hasUpToDateAdv) serverBuilder.addFlag(Server.Flag.featureStitchingAdvertisementRspecUptodate);
//        serverBuilder.addFlag(Server.Flag.workaroundAddExpiresAttributeToRequestRspec);

        if (am2conf.hasV2) {
            serviceBuilder = new ServiceBuilder();
            serverBuilder.addServiceBuilder(serviceBuilder);
            serviceBuilder.setUrn(TestCertHelper.am2Urn);
            serviceBuilder.setUrl(urlB_am2);
            serviceBuilder.setApi(ApiInfo.ApiName.GENI_AM.getId());
            serviceBuilder.setApiVersion("2");
            serviceBuilder.setId(serviceId++);
        }

        if (am2conf.hasV3) {
            serviceBuilder = new ServiceBuilder();
            serverBuilder.addServiceBuilder(serviceBuilder);
            serviceBuilder.setUrn(TestCertHelper.am2Urn);
            serviceBuilder.setUrl(urlB_am3);
            serviceBuilder.setApi(ApiInfo.ApiName.GENI_AM.getId());
            serviceBuilder.setApiVersion("3");
            serviceBuilder.setId(serviceId++);
        }

        if (true) {
            serviceBuilder = new ServiceBuilder();
            serverBuilder.addServiceBuilder(serviceBuilder);
            serviceBuilder.setUrn(TestCertHelper.sa2Urn);
            serviceBuilder.setUrl(urlB_pgSa1);
            serviceBuilder.setApi(ApiInfo.ApiName.PROTOGENI_SA.getId());
            serviceBuilder.setApiVersion("1");
            serviceBuilder.setId(serviceId++);
        }

        serverBuilder.setUrnTld(GeniUrn.parse(serverBuilder.getDefaultComponentManagerUrn()).getEncodedTopLevelAuthority());
        serverBuilder.setBaseUrl(serverBuilder.getServiceBuilders().get(0).getUrl());

        testbedBuilders.add(testbedBuilder);





        testbedBuilder = new TestbedBuilder();
        serverBuilder = new ServerBuilder();
        testbedBuilder.setId("test3");
        serverBuilder.setId(3);
        testbedBuilder.addServerBuilder(serverBuilder);
        testbedBuilder.setLongName(hrnC);
        serverBuilder.setName(hrnC);
        testbedBuilder.setDefaultComponentManagerUrn(TestCertHelper.scsUrn);
        serverBuilder.setDefaultComponentManagerUrn(TestCertHelper.scsUrn);
        serverBuilder.setServerType("test");
        serverBuilder.setCertificateChain(KeyUtil.x509certificateToPem(testCertHelper.authority3Cert));
        if (am3conf.hasAny) serverBuilder.addFlag(Server.Flag.featureStitchingAny);
        if (am3conf.hasUpToDateAdv) serverBuilder.addFlag(Server.Flag.featureStitchingAdvertisementRspecUptodate);
        serverBuilder.addFlag(Server.Flag.workaroundAddExpiresAttributeToRequestRspec);

        if (am3conf.hasV2) {
            serviceBuilder = new ServiceBuilder();
            serverBuilder.addServiceBuilder(serviceBuilder);
            serviceBuilder.setUrn(TestCertHelper.scsUrn);
            serviceBuilder.setUrl(urlC_am2);
            serviceBuilder.setApi(ApiInfo.ApiName.GENI_AM.getId());
            serviceBuilder.setApiVersion("2");
            serviceBuilder.setId(serviceId++);
        }

        if (am3conf.hasV3) {
            serviceBuilder = new ServiceBuilder();
            serverBuilder.addServiceBuilder(serviceBuilder);
            serviceBuilder.setUrn(TestCertHelper.scsUrn);
            serviceBuilder.setUrl(urlC_am3);
            serviceBuilder.setApi(ApiInfo.ApiName.GENI_AM.getId());
            serviceBuilder.setApiVersion("3");
            serviceBuilder.setId(serviceId++);
        }

        if (true) {
            serviceBuilder = new ServiceBuilder();
            serverBuilder.addServiceBuilder(serviceBuilder);
            serviceBuilder.setUrn(TestCertHelper.scsUrn);
            serviceBuilder.setUrl(urlC_scs);
            serviceBuilder.setApi(ApiInfo.ApiName.GENI_SCS.getId());
            serviceBuilder.setApiVersion("1");
            serviceBuilder.setId(serviceId++);
        }

        serverBuilder.setUrnTld(GeniUrn.parse(serverBuilder.getDefaultComponentManagerUrn()).getEncodedTopLevelAuthority());
        serverBuilder.setBaseUrl(serverBuilder.getServiceBuilders().get(0).getUrl());

        testbedBuilders.add(testbedBuilder);


        //Fake edge vlan

        testbedBuilder = new TestbedBuilder();
        serverBuilder = new ServerBuilder();
        testbedBuilder.setId("test4");
        serverBuilder.setId(4);
        testbedBuilder.addServerBuilder(serverBuilder);
        testbedBuilder.setLongName(hrnFake);
        serverBuilder.setName(hrnFake);
        testbedBuilder.setDefaultComponentManagerUrn(TestCertHelper.fakeAmUrn);
        serverBuilder.setDefaultComponentManagerUrn(TestCertHelper.fakeAmUrn);
        serverBuilder.setServerType("fake");

//        serverBuilder.setUrnTld(GeniUrn.parse(serverBuilder.getServiceBuilders().get(0).getUrn()).getEncodedTopLevelAuthority());
//        serverBuilder.setBaseUrl(serverBuilder.getServiceBuilders().get(0).getUrl());
        serverBuilder.setUrnTld(GeniUrn.parse(serverBuilder.getDefaultComponentManagerUrn()).getEncodedTopLevelAuthority());
        serverBuilder.setBaseUrl(null/*because no services*/);


        testbedBuilders.add(testbedBuilder);


        assert testbedBuilders.size() == 4;


        TestbedInfoSource testbedInfoSource = BasicTestbedInfoSource.createFromTestbedBuilders(testbedBuilders);
        assert testbedInfoSource.getTestbeds().size() == 4 : "testbedInfoSource.getTestbeds().size()="+testbedInfoSource.getTestbeds().size();
        assert testbedInfoSource.getServers().size() == 4 : "testbedInfoSource.getServers().size()="+testbedInfoSource.getServers().size();
        assert testbedInfoSource.getServiceCount() > 3 : "testbedInfoSource.getServiceCount()="+testbedInfoSource.getServiceCount();

        trustStore.addAuthorityCerts(testbedInfoSource);
        return testbedInfoSource;
    }

    public String getTestAuthorityUrnString() {
        return TestCertHelper.am1Urn;
    }
    public String getTestAuthority2UrnString() {
        return TestCertHelper.am2Urn;
    }
    public String getTestAuthority3UrnString() {
        return TestCertHelper.am3Urn;
    }

    public GeniUrn getTestAuthorityUrn() {
        return GeniUrn.parse(getTestAuthorityUrnString());
    }
    public GeniUrn getTestAuthority2Urn() {
        return GeniUrn.parse(getTestAuthority2UrnString());
    }
    public GeniUrn getTestAuthority3Urn() {
        return GeniUrn.parse(getTestAuthority3UrnString());
    }
}
