package org.hive2hive.core.processes.login;

import java.io.IOException;
import java.util.List;

import org.hive2hive.core.H2HConstants;
import org.hive2hive.core.H2HJUnitTest;
import org.hive2hive.core.H2HSession;
import org.hive2hive.core.exceptions.NoPeerConnectionException;
import org.hive2hive.core.exceptions.NoSessionException;
import org.hive2hive.core.model.versioned.Locations;
import org.hive2hive.core.network.NetworkManager;
import org.hive2hive.core.network.data.parameters.Parameters;
import org.hive2hive.core.processes.ProcessFactory;
import org.hive2hive.core.security.UserCredentials;
import org.hive2hive.core.utils.NetworkTestUtil;
import org.hive2hive.core.utils.TestExecutionUtil;
import org.hive2hive.core.utils.UseCaseTestUtil;
import org.hive2hive.core.utils.helper.TestFileAgent;
import org.hive2hive.processframework.exceptions.InvalidProcessStateException;
import org.hive2hive.processframework.exceptions.ProcessExecutionException;
import org.hive2hive.processframework.interfaces.IProcessComponent;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

/**
 * Tests the login procedure. Should not be able to login if the credentials are wrong.
 * 
 * @author Nico
 */
public class LoginTest extends H2HJUnitTest {

	private static List<NetworkManager> network;
	private static UserCredentials userCredentials;
	private static TestFileAgent fileAgent;

	@BeforeClass
	public static void initTest() throws Exception {
		testClass = LoginTest.class;
		beforeClass();

		network = NetworkTestUtil.createNetwork(DEFAULT_NETWORK_SIZE);
		userCredentials = generateRandomCredentials();

		UseCaseTestUtil.register(userCredentials, network.get(0));
		fileAgent = new TestFileAgent();
	}

	@Test
	public void testValidCredentials() throws ClassNotFoundException, IOException, NoSessionException,
			NoPeerConnectionException {
		NetworkManager client = NetworkTestUtil.getRandomNode(network);

		// login with valid credentials
		UseCaseTestUtil.login(userCredentials, client, fileAgent);

		Assert.assertNotNull(client.getSession());
		Assert.assertEquals(userCredentials.getUserId(), client.getUserId());

		// verify the locations map
		Locations locations = (Locations) client.getDataManager().get(
				new Parameters().setLocationKey(userCredentials.getUserId()).setContentKey(H2HConstants.USER_LOCATIONS));
		Assert.assertEquals(1, locations.getPeerAddresses().size());
	}

	@Test(expected = NoSessionException.class)
	public void testInvalidPassword() throws NoSessionException, InvalidProcessStateException, NoPeerConnectionException,
			ProcessExecutionException {
		UserCredentials wrongCredentials = new UserCredentials(userCredentials.getUserId(), randomString(),
				userCredentials.getPin());

		loginAndWaitToFail(wrongCredentials);
	}

	@Test(expected = NoSessionException.class)
	public void testInvalidPin() throws NoSessionException, InvalidProcessStateException, NoPeerConnectionException,
			ProcessExecutionException {
		UserCredentials wrongCredentials = new UserCredentials(userCredentials.getUserId(), userCredentials.getPassword(),
				randomString());

		loginAndWaitToFail(wrongCredentials);
	}

	@Test(expected = NoSessionException.class)
	public void testInvalidUserId() throws NoSessionException, InvalidProcessStateException, NoPeerConnectionException,
			ProcessExecutionException {
		UserCredentials wrongCredentials = new UserCredentials(randomString(), userCredentials.getPassword(),
				userCredentials.getPin());

		loginAndWaitToFail(wrongCredentials);
	}

	public H2HSession loginAndWaitToFail(UserCredentials wrongCredentials) throws InvalidProcessStateException,
			NoSessionException, NoPeerConnectionException {
		NetworkManager client = NetworkTestUtil.getRandomNode(network);
		SessionParameters sessionParameters = new SessionParameters(fileAgent);
		IProcessComponent<Void> loginProcess = ProcessFactory.instance().createLoginProcess(wrongCredentials,
				sessionParameters, client);
		TestExecutionUtil.executeProcessTillFailed(loginProcess);

		return client.getSession();
	}

	@AfterClass
	public static void endTest() throws IOException {
		NetworkTestUtil.shutdownNetwork(network);
		afterClass();
	}
}

@@ -1961,24 +1961,33 @@
 (network);%0A%0A
+%09%09try %7B%0A%09
 %09%09// login w
@@ -2010,16 +2010,17 @@
 tials%0A%09%09
+%09
 UseCaseT
@@ -2073,16 +2073,17 @@
 nt);%0A%0A%09%09
+%09
 Assert.a
@@ -2113,24 +2113,25 @@
 Session());%0A
+%09
 %09%09Assert.ass
@@ -2193,16 +2193,17 @@
 ());%0A%0A%09%09
+%09
 // verif
@@ -2222,16 +2222,17 @@
 ons map%0A
+%09
 %09%09Locati
@@ -2292,16 +2292,17 @@
 et(%0A%09%09%09%09
+%09
 new Para
@@ -2401,16 +2401,17 @@
 NS));%0A%09%09
+%09
 Assert.a
@@ -2463,16 +2463,69 @@
 ize());%0A
+%09%09%7D finally %7B%0A%09%09%09UseCaseTestUtil.logout(client);%0A%09%09%7D%0A
 %09%7D%0A%0A%09@Te
@@ -3719,41 +3719,8 @@
 ows 
-InvalidProcessStateException,%0A%09%09%09
 NoSe
@@ -3726,33 +3726,36 @@
 essionException,
- 
+%0A%09%09%09
 NoPeerConnection

Fix loginInvalidPinTest