package org.yacos.tests.core;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.yacos.core.article.Article;
import org.yacos.core.article.IArticleManager;
import org.yacos.core.conferences.Conference;
import org.yacos.core.conferences.IConferenceManager;
import org.yacos.core.exceptions.NoConferenceCreationTokenLeftException;
import org.yacos.core.exceptions.PKAlreadyUsedException;
import org.yacos.core.exceptions.UserEMailAlreadyExistsException;
import org.yacos.core.users.IUserManager;
import org.yacos.core.users.Role;
import org.yacos.core.users.Speciality;
import org.yacos.core.users.User;
import org.yacos.core.users.Role.RoleType;


public class UserManagerTest {
	private static IUserManager um;
	private static IConferenceManager cm;
	private static IArticleManager am;
	private static int conf_id;
	
	@BeforeClass
	public static void setUpManager() throws NamingException, PKAlreadyUsedException, UserEMailAlreadyExistsException, NoConferenceCreationTokenLeftException  {
		Context context = new InitialContext();

		um = (IUserManager) context.lookup("UserManagerBean/remote");
		am = (IArticleManager) context.lookup("ArticleManagerBean/remote");
		cm = (IConferenceManager) context.lookup("ConferenceManagerBean/remote");
		um.addUser("userManagerTestChairman", "", "First", "Last", "Yacos", "articleManagerTestChairman@yacos.com");
		if (cm.exists(1)){
			conf_id = 1;
		}else{
			cm.addConferenceCreationToken("userManagerTestChairman");
			Conference conf = cm.addConference("titi","articleManagerTestChairman","desc conf","info en plus",new Date(),new Date(),new Date(),new Date(),new Date());
			conf_id = conf.getId();
		}
	}
	
	@Before
	public void setup()throws PKAlreadyUsedException, UserEMailAlreadyExistsException{
		if(!um.exists("truc")){
			um.addUser("truc",User.hashPassword("pw"),"maxime","dagn","ipint", "e@ee.fr");
		}
		if(!um.exists("admin")){
			um.addUser("admin",User.hashPassword("pw"),"Admin","Admin","ipint", "admin@ee.fr");
		}
	}
	
	@Test
	public void addUserTest() throws PKAlreadyUsedException, UserEMailAlreadyExistsException{
		User user = um.addUser("maxmax",User.hashPassword("pw"),"maxime","dagn","ipint", "uie@e.fr");
		assertEquals(User.hashPassword("pw"), user.getPassword());
		um.removeUser("maxmax");
	}
	
	@Test
	public void getUserTest(){
		User user = um.getUser("truc");
		assertNotNull(user);
		assertEquals("truc", user.getLogin());
	}
	
	@Test
	public void addSpecialityTest(){
		um.addSpeciality("xml");
		List<Speciality> list = um.getSpecialities();
		assertFalse(list.isEmpty());
		Speciality spe = list.get(list.size()-1);
		assertEquals("xml", spe.getName());
		//test que l'on ne peut pas ajouter 2 fois la meme specialité
		int size = list.size();
		um.addSpeciality("xml");
		list = um.getSpecialities();
		assertEquals(size, list.size());
		um.removeSpeciality(spe.getId());
	}
	
	@Test
	public void addSpecialityToUserTest(){
		um.addSpeciality("xml");
		List<Speciality> list = um.getSpecialities();
		Speciality spe = list.get(list.size()-1);
		um.addSpecialityToUser(spe.getId(), "truc");
		list = um.getSpecialitiesFromUser("truc");
		assertFalse(list.isEmpty());
		um.removeSpeciality(spe.getId());
	}
	
	@Test
	public void removeSpecialitiesFromUser(){
		um.addSpeciality("xml");
		List<Speciality> list = um.getSpecialities();
		Speciality spe = list.get(list.size()-1);
		um.addSpecialityToUser(spe.getId(), "truc");
		um.removeSpecialityFromUser(spe.getId(), "truc");
		assertTrue(um.getSpecialities().isEmpty());
	}
	
	@Test
	public void getUserByRoleType(){
		@SuppressWarnings("unused")
		Role role = cm.addRole(RoleType.PCMEMBER, "truc", conf_id);
		List<User> list = um.getUsers(conf_id,RoleType.PCMEMBER);
		assertFalse(list.isEmpty());
		//on recupere le dernier user de la liste
		User user = list.get(list.size()-1);
		assertEquals("truc",user.getLogin());
	}
	
	
	
	@Test
	public void getPCMemberForArticleTest(){
		cm.addRole(RoleType.PCMEMBER, "truc", conf_id);
		Article article = am.addArticle("title","topic","Abstract", "url_article","admin",
				new ArrayList<String>(),Article.State.SUBMITED,conf_id);
		am.assignArticleToPCMember(article.getId(), "truc");
		List <User> list = um.getPCMemberForArticle(article.getId());
		assertFalse("liste vide",list.isEmpty());
		assertEquals("truc",list.get(list.size()-1).getLogin());
		am.unassignArticleToPCMember(article.getId(), "truc");
		am.removeArticle(article.getId());
	}
			
	@Test
	public void getRefereesForArticleTest(){
		cm.addRole(RoleType.PCMEMBER, "truc", conf_id);
		Article article = am.addArticle("title","topic","Abstract", "url_article","truc",
				new ArrayList<String>(),Article.State.SUBMITED,conf_id);
		am.delegateArticleToReferee(article.getId(), "truc", "admin");
		List <User> list = um.getRefereesOfPcMemberForArticle("admin",article.getId());
		assertFalse("liste vide",list.isEmpty());
		assertEquals("truc",list.get(list.size()-1).getLogin());
		am.undelegateArticleToReferee(article.getId(), "truc", "admin");
		list = um.getRefereesOfPcMemberForArticle("admin",article.getId());
		assertTrue("liste non vide",list.isEmpty());
	}
	
	@Test
	public void conferenceCreationTokensTest() throws Exception {
		assertFalse(cm.canCreateConference("truc"));
		cm.addConferenceCreationToken("truc");
		assertTrue(cm.canCreateConference("truc"));
		assertEquals(1, cm.conferenceCreationTokens("truc"));
		cm.addConferenceCreationToken("truc");
		assertTrue(cm.canCreateConference("truc"));
		assertEquals(2, cm.conferenceCreationTokens("truc"));
		cm.useConferenceCreationToken("truc");
		assertTrue(cm.canCreateConference("truc"));
		assertEquals(1, cm.conferenceCreationTokens("truc"));
		cm.useConferenceCreationToken("truc");
		assertFalse(cm.canCreateConference("truc"));
		assertEquals(0, cm.conferenceCreationTokens("truc"));
		try {
			cm.useConferenceCreationToken("truc");
			fail("Using a token when token count is 0 should have raised an exception");
		} catch (NoConferenceCreationTokenLeftException e) {
		}
	}
	
	
	@After
	public void ControleUser() throws PKAlreadyUsedException{
		if(um.exists("truc")){
			um.removeUser("truc");
		}
		if(um.exists("admin")){
			um.removeUser("admin");
		}
		um.removeUser("userManagerTestChairman");
	}
	

}
