package be.iminds.ilabt.jfed.highlevel.model;

import be.iminds.ilabt.jfed.CorePreferencesModule;
import be.iminds.ilabt.jfed.highlevel.HighLevelModule;
import be.iminds.ilabt.jfed.highlevel.LowLevelModule;
import be.iminds.ilabt.jfed.highlevel.MockGeniUserModule;
import be.iminds.ilabt.jfed.highlevel.SfaOnlyExperimentModule;
import be.iminds.ilabt.jfed.lowlevel.GeniUser;
import be.iminds.ilabt.jfed.lowlevel.GeniUserProvider;
import be.iminds.ilabt.jfed.lowlevel.api.user_spec.UserSpec;
import be.iminds.ilabt.jfed.util.JavaFXTest;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Test;

import javax.inject.Inject;
import java.util.*;


/**
 * UserSpecHelperTest
 */
public class UserSpecHelperTest extends JavaFXTest {
    private static String rspec1 = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" +
            "<rspec generated=\"2014-05-30T14:14:02.972+02:00\" " +
            "       generated_by=\"Experimental jFed Rspec Editor\"" +
            "       type=\"request\" " +
            "       xsi:schemaLocation=\"http://www.geni.net/resources/rspec/3 http://www.geni.net/resources/rspec/3/request.xsd\" " +
            "       xmlns=\"http://www.geni.net/resources/rspec/3\" xmlns:jFed=\"http://jfed.iminds.be/rspec/ext/jfed/1\" " +
            "       xmlns:jFedBonfire=\"http://jfed.iminds.be/rspec/ext/jfed-bonfire/1\" " +
            "       xmlns:delay=\"http://www.protogeni.net/resources/rspec/ext/delay/1\" " +
            "       xmlns:jfed-ssh-keys=\"http://jfed.iminds.be/rspec/ext/jfed-ssh-keys/1\" " +
            "       xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n" +
            "    <node client_id=\"node0\" component_manager_id=\"urn:publicid:IDN+wall1.ilabt.iminds.be+authority+cm\" exclusive=\"true\">\n" +
            "        <sliver_type name=\"raw-pc\"/>\n" +
            "        <jFed:location x=\"64.0\" y=\"60.0\"/>\n" +
            "        <jFed:nodeDescription>simple-node</jFed:nodeDescription>\n" +
            "    </node>\n" +
            "  \n" +
            "   <jfed-ssh-keys:user-ssh-keys user=\"urn:publicid:IDN+wall2.ilabt.iminds.be+user+wvdemeer\">\n" +
            "        <jfed-ssh-keys:sshkey>ssh-rsa myextrakey</jfed-ssh-keys:sshkey>\n" +
            "    </jfed-ssh-keys:user-ssh-keys>\n" +
            "   <jfed-ssh-keys:user-ssh-keys user=\"urn:publicid:IDN+example.com+user+tester\">\n" +
            "        <jfed-ssh-keys:sshkey>ssh-rsa blabla</jfed-ssh-keys:sshkey>\n" +
            "    </jfed-ssh-keys:user-ssh-keys>\n" +
            "    <jfed-ssh-keys:user-ssh-keys user=\"urn:publicid:IDN+example.com+user+tester2\">\n" +
            "        <jfed-ssh-keys:sshkey>ssh-rsa blibli</jfed-ssh-keys:sshkey>\n" +
            "        <jfed-ssh-keys:sshkey>ssh-rsa bloblo</jfed-ssh-keys:sshkey>\n" +
            "    </jfed-ssh-keys:user-ssh-keys>\n" +
            "</rspec>";
    private static String rspec2 = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" +
            "<rspec generated=\"2014-05-30T14:14:02.972+02:00\" " +
            "       generated_by=\"Experimental jFed Rspec Editor\" " +
            "       type=\"request\" " +
            "       xsi:schemaLocation=\"http://www.geni.net/resources/rspec/3 http://www.geni.net/resources/rspec/3/request.xsd\" " +
            "       xmlns=\"http://www.geni.net/resources/rspec/3\" " +
            "       xmlns:jFed=\"http://jfed.iminds.be/rspec/ext/jfed/1\" " +
            "       xmlns:delay=\"http://www.protogeni.net/resources/rspec/ext/delay/1\" " +
            "       xmlns:jfed-ssh-keys=\"http://jfed.iminds.be/rspec/ext/jfed-ssh-keys/1\" " +
            "       xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n" +
            "    <node client_id=\"node0\" component_manager_id=\"urn:publicid:IDN+wall1.ilabt.iminds.be+authority+cm\" exclusive=\"true\">\n" +
            "        <sliver_type name=\"raw-pc\"/>\n" +
            "        <jFed:location x=\"64.0\" y=\"60.0\"/>\n" +
            "        <jFed:nodeDescription>simple-node</jFed:nodeDescription>\n" +
            "    </node>\n" +
            "  \n" +
            "   <jfed-ssh-keys:user-ssh-keys user=\"urn:publicid:IDN+example.com+user+tester\">\n" +
            "        <jfed-ssh-keys:sshkey>ssh-rsa blabla2</jfed-ssh-keys:sshkey>\n" +
            "    </jfed-ssh-keys:user-ssh-keys>\n" +
            "   <jfed-ssh-keys:user-ssh-keys>\n" +
            "        <jfed-ssh-keys:sshkey>ssh-rsa myextrakey2</jfed-ssh-keys:sshkey>\n" +
            "    </jfed-ssh-keys:user-ssh-keys>\n" +
            "    <jfed-ssh-keys:user-ssh-keys user=\"urn:publicid:IDN+example.com+user+tester2\">\n" +
            "        <jfed-ssh-keys:sshkey>ssh-rsa blibli2</jfed-ssh-keys:sshkey>\n" +
            "        <jfed-ssh-keys:sshkey>ssh-rsa bloblo2</jfed-ssh-keys:sshkey>\n" +
            "    </jfed-ssh-keys:user-ssh-keys>\n" +
            "</rspec>";

    @Inject
    private SfaModel sfaModel;
    @Inject
    private GeniUserProvider geniUserProvider;

    private GeniUser loggedInUser;

    @BeforeSuite
    private void prepareSuite(){

        Injector injector = Guice.createInjector(new MockGeniUserModule(), new HighLevelModule(),
                new SfaOnlyExperimentModule(), new LowLevelModule(), new CorePreferencesModule());

        injector.injectMembers(this);
        System.out.println("Injecting dependencies");

        loggedInUser = geniUserProvider.getLoggedInGeniUser();


    }


    @BeforeMethod
    private void prepare() {
        this.sfaModel.addUserKey(loggedInUser.getUserUrn(), "ssh-rsa myexistingkeyA");
        this.sfaModel.addUserKey(loggedInUser.getUserUrn(), "ssh-rsa myexistingkeyB");


    }


    private void testGetMergedUserSpecs(String rspec, String suffix) {
        assert geniUserProvider != null;

        List<UserSpec> rspecUserSpecs = UserSpecHelper.getUserSpecFromRspecExt(rspec);
        Assert.assertNotNull(rspecUserSpecs);
        Assert.assertEquals(rspecUserSpecs.size(), 3);

        Assert.assertNotNull(sfaModel.getUserKeys(loggedInUser.getUserUrn()));
        Assert.assertEquals(sfaModel.getUserKeys(loggedInUser.getUserUrn()).size(), 2);

        List<UserSpec> userUserSpecs = UserSpecHelper.getUserUserSpecList(geniUserProvider, sfaModel);
        Assert.assertNotNull(userUserSpecs);
        Assert.assertEquals(userUserSpecs.size(), 1);
        Assert.assertNotNull(userUserSpecs.get(0).getSshKey());
        Assert.assertEquals(userUserSpecs.get(0).getSshKey().size(), 2);

        List<UserSpec> res = UserSpecHelper.getMergedUserSpecs(geniUserProvider, sfaModel, rspec);

        Set<String> users = new HashSet<>();
        Map<String, UserSpec> userSpecByUserUrn = new HashMap<>();
        System.out.println("\nMerged UserSpec List:");
        for (UserSpec us : res) {
            System.out.println("   " + us);
            users.add(us.getUrn());
            userSpecByUserUrn.put(us.getUrn(), us);
        }
        System.out.println();

        Assert.assertTrue(users.contains(MockGeniUserModule.LOGGED_IN_USER_URN_STRING));
        Assert.assertTrue(users.contains("urn:publicid:IDN+example.com+user+tester"));
        Assert.assertTrue(users.contains("urn:publicid:IDN+example.com+user+tester2"));

        UserSpec loggedInUserSpec = userSpecByUserUrn.get(MockGeniUserModule.LOGGED_IN_USER_URN_STRING);
        UserSpec testerUserSpec = userSpecByUserUrn.get("urn:publicid:IDN+example.com+user+tester");
        UserSpec tester2UserSpec = userSpecByUserUrn.get("urn:publicid:IDN+example.com+user+tester2");

        Assert.assertEquals(loggedInUserSpec.getSshKey().size(), 3);
        Assert.assertEquals(testerUserSpec.getSshKey().size(), 1);
        Assert.assertEquals(tester2UserSpec.getSshKey().size(), 2);

        Assert.assertTrue(loggedInUserSpec.getSshKey().contains("ssh-rsa myexistingkeyA"));
        Assert.assertTrue(loggedInUserSpec.getSshKey().contains("ssh-rsa myexistingkeyB"));
        Assert.assertTrue(loggedInUserSpec.getSshKey().contains("ssh-rsa myextrakey" + suffix));

        Assert.assertTrue(testerUserSpec.getSshKey().contains("ssh-rsa blabla" + suffix));
        Assert.assertTrue(tester2UserSpec.getSshKey().contains("ssh-rsa blibli" + suffix));
        Assert.assertTrue(tester2UserSpec.getSshKey().contains("ssh-rsa bloblo" + suffix));
    }

    @Test
    public void testGetMergedUserSpecs1() {
        testGetMergedUserSpecs(rspec1, "");
    }

    @Test
    public void testGetMergedUserSpecs2() {
        testGetMergedUserSpecs(rspec2, "2");
    }

}
