package be.iminds.ilabt.jfed.lowlevel.api.test;

import be.iminds.ilabt.jfed.log.Logger;
import be.iminds.ilabt.jfed.lowlevel.*;
import be.iminds.ilabt.jfed.lowlevel.api.AggregateManager3;
import be.iminds.ilabt.jfed.lowlevel.connection.JFedConnectionProvider;
import be.iminds.ilabt.jfed.lowlevel.connection.SfaConnection;
import be.iminds.ilabt.jfed.preferences.JFedPreferences;
import be.iminds.ilabt.jfed.testing.base.ApiTest;
import be.iminds.ilabt.jfed.util.TargetAuthority;

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

/**
 * SimpleTestAggregateManager3. One simple test of "Geni Aggregate Manager API v3"
 *
 * This is little more than a connectivity test and one basic test of XmlRpc and GetVersion.
 *
 * Use TestAggregateManager3 for a lot more tests of the "Geni Aggregate Manager API v3". (And also for more thorough tests of GetVersion)
 */
public class ConnectivityTestAggregateManager3 extends ApiTest {
    @Inject
    public ConnectivityTestAggregateManager3(Logger logger, TargetAuthority testedAuthority, GeniUserProvider geniUserProvider, JFedConnectionProvider connectionProvider, TestbedInfoSource testbedInfoSource, JFedPreferences jFedPreferences) {
        super(logger, testedAuthority, geniUserProvider, connectionProvider, testbedInfoSource, jFedPreferences);
    }

    public String getTestDescription() {
        return "One simple \"Geni Aggregate Manager API v3\" Test (XmlRpc and GetVersion). This is mainly useful to test connectivity to the tested AM.";
    }

    private AggregateManager3 am3;

    public SfaConnection getAM3Connection() throws JFedException {
        return (SfaConnection) connectionProvider.getConnectionByAuthority(user, testedAuthority.getServerToConnect(), new ApiInfo.Api(ApiInfo.ApiName.GENI_AM, 3));
    }

    /**
     * Check for correctness of a AM2 XmlRpc result. Should be tested for each reply received.
     * */
    public void testAM2CorrectnessXmlRpcResult(Map res) {
        Object code = res.get("code");
        Object value = res.get("value");
        Object output = res.get("output");
        assertNotNull(code, "testAM3CorrectnessXmlRpcResult code == null in "+res);
        assertNotNull(value, "testAM3CorrectnessXmlRpcResult value == null in "+res);
        assertInstanceOf(code, Map.class, "testAM3CorrectnessXmlRpcResult code is not Map in "+res);
        Map codeHt = (Map) code;
        Object genicode = codeHt.get("geni_code");
        assertNotNull(genicode, "testAM3CorrectnessXmlRpcResult code does not contain \"geni_code\" in "+res);
        assertEquals(genicode.getClass(), Integer.class, "testAM3CorrectnessXmlRpcResult code.geni_code is not int in "+res);

        int genicodevalue = (Integer) genicode;
        //output should be present if code is not 0
        if (genicodevalue != 0) {
            assertNotNull(output, "testAM3CorrectnessXmlRpcResult: while geni_code is non success ("+genicodevalue+"), output == null in "+res);
            assertEquals(output.getClass(), String.class, "testAM3CorrectnessXmlRpcResult: while geni_code is non success ("+genicodevalue+"), output is not String (it is "+output.getClass().getName()+" with value \""+output.toString()+"\") in \"+res+\"");
        }
        else {
            //this is a connectivity test, we don't warn here, we just make a note of it.
            if (output == null)
                note("testAM3CorrectnessXmlRpcResult: while geni_code is success ("+genicodevalue+"), output is ommited. This is allowed by the API.");
            if (output != null && !(output instanceof String))
                note("testAM32CorrectnessXmlRpcResult: while geni_code is success ("+genicodevalue+"), output is not String (it is "+output.getClass().getName()+" with value \""+output.toString()+"\"). This is allowed but not recommended by jFed.");
        }
    }

    public void setUp() {


        am3 = new AggregateManager3(logger, jFedPreferences);
    }


    private Map versionRawResult = null;
    private AggregateManager3.VersionInfo versionInfo = null;
    @Test
    public void testGetVersionXmlRpcCorrectness() throws JFedException {
        AggregateManager3.AggregateManagerReply<AggregateManager3.VersionInfo> reply = am3.getVersion(getAM3Connection());

        testAM2CorrectnessXmlRpcResult(reply.getRawResult());

        //GetVersion is the only method where we have to check for something extra in the raw XMLRPC result
        versionRawResult = reply.getRawResult();
        assertNotNull(versionRawResult);

        Object ver = versionRawResult.get("geni_api"); //this is here for backward compatibility with v1. GetVersion returns this on all versions.
        assert(ver != null);
        assert(ver instanceof Integer);
        int v = (Integer) ver;
        assertEquals(v, 3, "AM (backward compatibility \"geni_api\" field) is not version 3");


        assertEquals(reply.getGeniResponseCode(), GeniAMResponseCode.GENIRESPONSE_SUCCESS, "GeniResponse code is not SUCCESS (0)");

        versionInfo = reply.getValue();
        assertNotNull(versionInfo);
        assertEquals(versionInfo.getApi(), 3, "AM is not version 3");
    }
}
