/**
 * 
 */
package org.yacos.core.evaluation;


import java.util.List;
import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.transaction.UserTransaction;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.yacos.core.article.Article;
import org.yacos.core.conferences.Conference;
import org.yacos.core.users.User;

/**
 * @author christiancorsano
 *
 */
@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class EvaluationManagerBean implements IEvaluationManager {
	@PersistenceContext
	EntityManager em;
	@Resource
	UserTransaction ut;
	
	protected final Log logger = LogFactory.getLog(getClass());
	
	@SuppressWarnings("unchecked")
	public List<Criterion> getCriterions(int confId){	
		//Query q = em.createQuery("from Criterion");
		Query query = em.createQuery("from Criterion where conference_id = ?");
		query.setParameter(1, confId);		 		
		return query.getResultList();
		//return q.getResultList();
	}
	
	/*
	 * (non-Javadoc)
	 * @see org.yacos.core.evaluation.IEvaluationManager#getCriterions()
	 */
	@SuppressWarnings("unchecked")
	public List<Criterion> getCriterions() {
		Query query = em.createQuery("from Criterion");
		return query.getResultList();
	}
	
	

	public Criterion addCriterion(String name, Integer min_rating,
			Integer max_rating, int confId) {
		Criterion crit = null;
		try {
			ut.begin();
			crit = new Criterion();
			crit.setName(name);
			crit.setMin_rating(min_rating);
			crit.setMax_rating(max_rating);
			Conference conf = em.find(Conference.class, confId);
			crit.setConference(conf);
			em.persist(crit);
			ut.commit();
		} catch (Exception e) {
			try {
				ut.rollback();
			} catch (Exception e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
		}
		return crit;
	}

	public void updateCriterion(Criterion criterion) {
		try {
			ut.begin();
			Criterion persistedCriterion = em.find(Criterion.class, criterion.getId());
			Conference conference = em.find(Conference.class, criterion.getConference().getId());
			persistedCriterion.setName(criterion.getName());
			persistedCriterion.setMin_rating(criterion.getMin_rating());
			persistedCriterion.setMax_rating(criterion.getMax_rating());
			persistedCriterion.setConference(conference);
			ut.commit();
		} catch (Exception e) {
			try {
				ut.rollback();
			} catch (Exception e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
		}
	}

	public void removeCriterion(int criterionId) {
		try {
			ut.begin();
			Criterion criterion = em.find(Criterion.class, criterionId);
			em.remove(criterion);
			ut.commit();
		} catch (Exception e) {
			try {
				ut.rollback();
			} catch (Exception e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
		}
	}
	
	public Criterion getCriterion(int criterionId) {
		return em.find(Criterion.class, criterionId);
	}


	/**
	 * methodes du Report 
	 */
	
	public Report addReport(int articleId, String commentPCMember, String commentAuthor, List<Rating> ratings, 
			String refereeLogin) {
		Report report = null;
		try {
			ut.begin();
			report = new Report();
			User referee = em.find(User.class, refereeLogin);
			Article article = em.find(Article.class, articleId);
			report.setReferee(referee);
			report.setArticle(article);
			report.setCommentPCMember(commentPCMember);
			report.setCommentAuthor(commentAuthor);
			report.setRatings(ratings);
			em.persist(report);
			ut.commit();
		} catch (Exception e) {
			try {
				ut.rollback();
			} catch (Exception e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
		}
		return report;
	}

	public void updateReport(Report report) {
		try {
			ut.begin();
			Report persistedReport = em.find(Report.class, report.getId());
			Article article = em.find(Article.class, report.getArticle().getId());
			User referee = em.find(User.class, report.getReferee().getLogin());
			persistedReport.setCommentAuthor(report.getCommentAuthor());
			persistedReport.setCommentPCMember(report.getCommentPCMember());
			persistedReport.setArticle(article);
			persistedReport.setReferee(referee);
			ut.commit();
		} catch (Exception e) {
			try {
				ut.rollback();
			} catch (Exception e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
		}
	}
	
	public void removeReport(int reportId) {
		try {
			ut.begin();
			Report report = em.find(Report.class, reportId);
			em.remove(report);
			ut.commit();
		} catch (Exception e) {
			try {
				ut.rollback();
			} catch (Exception e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
		}
	}
	
	public Report getReport(int reportId){
		Report report = em.find(Report.class, reportId);
		return report;
	}
	
	public Report getReportforArticleAndReferee(int articleId, String refereeLogin) {
		Query q = em.createQuery("from Report r where article_id= ? and referee_id= ?");
		q.setParameter(1, articleId);
		q.setParameter(2, refereeLogin);
		
		try {
			return (Report) q.getSingleResult();
		}
		catch (javax.persistence.NoResultException e) {
			return null;
		}
	}

	@SuppressWarnings("unchecked")
	public List<Report> getReportsForArticle(int articleId) {
		Query q = em.createQuery("from Report r where article_id= ?");
		q.setParameter(1, articleId);
		return q.getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<Report> getReportsForReferee(String refereeLogin) {
		Query q = em.createQuery("from Report r where referee_id= ?");
		q.setParameter(1, refereeLogin);
		return q.getResultList();
	}
	
	/*
	 * rating methods
	 */
	
	public Rating addRating(Integer value, Integer criterionId, Integer reportId) {
		Rating rating = null;
		try {
			ut.begin();
			Criterion criterion = em.find(Criterion.class, criterionId);
			Report report = em.find(Report.class,reportId);
			rating = new Rating(value,criterion,report);
			em.persist(rating);
			ut.commit();
		} catch (Exception e) {
			try {
				ut.rollback();
			} catch (Exception e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
		}
		return rating;
	}
	
	@SuppressWarnings("unchecked")
	public List<Rating> getRatingForReport(Integer reportId){
		Query q = em.createQuery("select r.ratings from Report r where r.id=?");
		q.setParameter(1, reportId);
		return q.getResultList();
	}
	public void removeRating(Criterion criterion, Report report) {
		try {
			ut.begin();
			Criterion persistedCriterion = em.find(Criterion.class, criterion.getId());
			Report persistedReport = em.find(Report.class,report.getId());
			Rating rating = em.find(Rating.class, new RatingPK(persistedCriterion,persistedReport));
			em.remove(rating);
			ut.commit();
		} catch (Exception e) {
			try {
				ut.rollback();
			} catch (Exception e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
		}
	}
	
	public Rating updateRating(Rating rating) {
		try {
			ut.begin();
			Criterion criterion = em.find(Criterion.class, rating.getCriterion().getId());
			Report report = em.find(Report.class,rating.getReport().getId());
			RatingPK ratingId = new RatingPK(criterion,report);
			Rating persistedRating = em.find(Rating.class, ratingId);
			// We suppose that the criterion and report didn't change,
			//  as such a change would result in modifying the Rating id
			persistedRating.setValue(rating.getValue());
			ut.commit();
		} catch (Exception e) {
			try {
				ut.rollback();
			} catch (Exception e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
		}
		return rating;
	}
	
}
