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.assertNull;
import static org.junit.Assert.assertTrue;

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.evaluation.Criterion;
import org.yacos.core.evaluation.IEvaluationManager;
import org.yacos.core.evaluation.Rating;
import org.yacos.core.evaluation.Report;
import org.yacos.core.exceptions.PKAlreadyUsedException;
import org.yacos.core.users.IUserManager;

@SuppressWarnings("unused")
public class EvaluationManagerTest {

	private static IEvaluationManager em;
	private static IArticleManager am;
	private static IConferenceManager cm;
	private static IUserManager um;
	private int confId;
	private Article article;
	private int articleId;
	private int critId;
	
	@BeforeClass
	public static void setUpManager() throws NamingException, PKAlreadyUsedException {
		Context context = new InitialContext();
		cm = (IConferenceManager) context.lookup("ConferenceManagerBean/remote");
		em = (IEvaluationManager) context.lookup("EvaluationManagerBean/remote");
		am = (IArticleManager) context.lookup("ArticleManagerBean/remote");
		um = (IUserManager) context.lookup("UserManagerBean/remote");
	}
	
	@Before
	public void initDB() throws Exception{
		if(! um.exists("evaluationManagerTest")){
			um.addUser("evaluationManagerTest", "pw", "first", "last", "yacos", "evaluationManagerTest@yacos.com");
		}
		if(! um.exists("evaluationManagerTest2")){
			um.addUser("evaluationManagerTest2", "pw", "first", "last", "yacos", "evaluationManagerTest@yacos.com");
		}
		cm.addConferenceCreationToken("evaluationManagerTest");
		Conference conf = cm.addConference("titre","evaluationManagerTest","desc conf","info en plus",new Date(),new Date(),new Date(),new Date(),new Date(),
				0,
				false,
				false,
				false,
				false,
				"Other infos");
		confId = conf.getId();
		Criterion crit = em.addCriterion("name", 0, 4, confId);
		critId = crit.getId();
		
		article = am.addArticle("title article max","topic","Abstract", "url_article",
				"evaluationManagerTest",	new ArrayList<String>(), Article.State.SUBMITED,	confId);
		articleId = article.getId();
	}
	
	@After
	public void cleanDB(){
		if(am.existsArticle(articleId)){
			am.removeArticle(articleId);
		}
		if(em.getCriterion(critId)!=null){
			em.removeCriterion(critId);
		}
		if(cm.exists(confId)){
			cm.remove(confId);
		}
		um.removeUser("evaluationManagerTest");
		um.removeUser("evaluationManagerTest2");
	}
	
	@Test
	public void add_et_getCriterionsTest() {
		Criterion crit = em.getCriterion(critId);
		assertNotNull(crit);
		assertEquals(crit.getName(), em.getCriterion(crit.getId()).getName());
	}
	
	@Test
	public void getCriterionsTest() throws NamingException{
		List<Criterion> list = em.getCriterions(confId);
		assertFalse("liste vide",list.isEmpty());
	}
	
	@Test
	public void updateCriterionTest(){
		Criterion crit = em.getCriterion(critId);
		crit.setName("autre");
		em.updateCriterion(crit);
		crit = em.getCriterion(crit.getId());
		assertEquals("autre", crit.getName());
	}
	
	@Test
	public void removeCriterion(){
		Criterion crit = em.getCriterion(critId);
		em.removeCriterion(crit.getId());
	}
	
	@Test
	public void AddReportTest(){
		List<Rating> ratings = new ArrayList<Rating>();
		Report report = em.addReport(article.getId(), "commentPCMember", "commentAuthor", ratings, "evaluationManagerTest");
		
		//assertNotNull(em.getReportforArticleAndReferee(article.getId(), "evaluationManagerTest"));
		
		Report testReport = em.getReport(report.getId());
		assertNotNull(testReport);
		
		assertEquals("commentAuthor", testReport.getCommentAuthor());
		em.removeReport(testReport.getId());
	}
	
	@Test
	public void updateReportTest(){
		Report report = em.addReport(article.getId(), "commentPCMember", "commentAuthor", new ArrayList<Rating>(), "evaluationManagerTest");
		report.setCommentPCMember("autre");
		em.updateReport(report);
		assertEquals("autre", em.getReport(report.getId()).getCommentPCMember());
	}
	
	@Test
	public void removeReportTest(){
		Report report = em.addReport(article.getId(), "report a virer", "commentAuthor", new ArrayList<Rating>(), "evaluationManagerTest");
		int reportId = report.getId();
		Criterion c = em.addCriterion("toto", 1, 5, confId);
		Rating r = em.addRating(2, c.getId(), reportId);
		List<Rating> listRating = em.getRatingForReport(reportId);
		for (Rating r2 : listRating) {
			em.removeRating(r2.getCriterion(), r2.getReport());
		}
		
		em.removeReport(report.getId());
		assertNull(em.getReport(reportId));
	}	
	
	
	@Test
	public void getReportforArticleAndRefereeTest(){
		Report report = em.addReport(article.getId(), "report a virer", "commentAuthor", new ArrayList<Rating>(), "evaluationManagerTest");
		Report report2 =em.getReportforArticleAndReferee(article.getId(), "evaluationManagerTest");
		assertEquals(report.getId(), report2.getId());
	}

	
	@Test
	public void getReportsForArticleTest(){
			em.addReport(article.getId(), "report a virer", "commentAuthor", new ArrayList<Rating>(), "evaluationManagerTest");
			em.addReport(article.getId(), "report a virer", "commentAuthor", new ArrayList<Rating>(), "evaluationManagerTest2");
			List <Report> list = em.getReportsForArticle(article.getId());
			assertTrue(list.size() == 2);
			
	}
	@Test
	public void getReportsForRefereeTest(){
		em.addReport(article.getId(), "report a virer", "commentAuthor", new ArrayList<Rating>(), "evaluationManagerTest");
		em.addReport(article.getId(), "report a virer", "commentAuthor", new ArrayList<Rating>(), "evaluationManagerTest2");
		List <Report> list = em.getReportsForReferee("evaluationManagerTest");
		assertFalse(list.isEmpty());
		//assertTrue(list.size() == 1);
	}
	
	@Test
	public void getRatingsFromReportTest(){
		Criterion criterion = em.addCriterion("crit�re1", 0, 3, confId);
		Report report = em.addReport(article.getId(), "report a virer", "commentAuthor", new ArrayList<Rating>(), "evaluationManagerTest");
		em.addRating(2,criterion.getId(),report.getId());
		assertFalse(em.getRatingForReport(report.getId()).isEmpty());
		em.removeRating(criterion, report);
	}
	
	@Test
	public void updateRatingTest(){
		Criterion criterion = em.addCriterion("crit�re1", 0, 3, confId);
		Report report = em.addReport(article.getId(), "report a virer", "commentAuthor", new ArrayList<Rating>(), "evaluationManagerTest");
		Rating rating = em.addRating(2,criterion.getId(),report.getId());
		rating.setValue(1);
		em.updateRating(rating);
		assertEquals(1, em.getRatingForReport(report.getId()).size());
		rating = em.getRatingForReport(report.getId()).get(0);
		assertEquals(1, rating.getValue());
		em.removeRating(criterion, report);	
	}
	
}
