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

import be.iminds.ilabt.jfed.CorePreferencesModule;
import be.iminds.ilabt.jfed.MockHttpRepliesTestCoreModule;
import be.iminds.ilabt.jfed.TestAuthoritiesModule;
import be.iminds.ilabt.jfed.TestUserModule;
import be.iminds.ilabt.jfed.highlevel.HighLevelModule;
import be.iminds.ilabt.jfed.highlevel.SfaOnlyExperimentModule;
import be.iminds.ilabt.jfed.highlevel.tasks.HighLevelTaskFactory;
import be.iminds.ilabt.jfed.lowlevel.TestCertHelper;

import be.iminds.ilabt.jfed.fedmon.webapi.service.json.*;
import be.iminds.ilabt.jfed.lowlevel.TestbedInfoSource;
import be.iminds.ilabt.jfed.lowlevel.connection.MockReplyLibrary;
import com.google.inject.Guice;
import com.google.inject.Injector;
import javafx.embed.swing.JFXPanel;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;

/**
 * HighLevelControllerTest
 */
public class HighLevelControllerMockHttpRepliesTest {
    private Server testAuth;

    private MockReplyLibrary mockReplyLibrary;

    private TestbedInfoSource testbedInfoSource;

    private TaskThread tt;
    private HighLevelTaskFactory hltf;


    private Injector injector;

    @BeforeMethod
    public void setUp() throws Exception {
        //initialize JavaFX
        new JFXPanel();

        mockReplyLibrary = new MockReplyLibrary();

        MockHttpRepliesTestCoreModule testCoreModule =  new MockHttpRepliesTestCoreModule();
        testCoreModule.addMockReply(mockReplyLibrary.getVersion3());

        try {
            injector = Guice.createInjector(testCoreModule,
                    new TestUserModule(),
                    new CorePreferencesModule(),
                    new TestAuthoritiesModule(),
                    new HighLevelModule(),
                    new SfaOnlyExperimentModule()
            );
        } catch (Exception | AssertionError e) {
            throw new RuntimeException("Error setting up injector", e);
        }

        TestCertHelper testCertHelper = injector.getInstance(TestCertHelper.class);
        this.testbedInfoSource = injector.getInstance(TestbedInfoSource.class);
        this.tt = injector.getInstance(TaskThread.class);
        this.hltf = injector.getInstance(HighLevelTaskFactory.class);

        testAuth = testbedInfoSource.getByUrnExact(TestCertHelper.am1Urn);
    }

    @Test
    public void basicHighLevelControllerTest() throws InterruptedException {
        CountDownLatch countdownLatch = new CountDownLatch(2);

        Task t = hltf.getVersion(testAuth);
        TaskExecutionFinishedCallback callback = (task, taskExecution, state) -> {
            System.out.println("GetVersion completed");
            countdownLatch.countDown();
        };
        tt.addTask(t, callback);

        countdownLatch.countDown();
        countdownLatch.await(1, TimeUnit.SECONDS);

        assertThat("getVersion was not called exactly once", mockReplyLibrary.getVersion3().usageCount(), equalTo(1));
    }
}
