package org.yacos.core.conferences;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.yacos.core.evaluation.Criterion;
import org.yacos.core.exceptions.ConferenceDoesntExistException;
import org.yacos.core.system.InvitationToken;
import org.yacos.core.system.InvitationTokenPK;
import org.yacos.core.users.Role;
import org.yacos.core.users.RolePK;
import org.yacos.core.users.User;
import org.yacos.core.users.Role.RoleType;


@Stateless
public class ConferenceManagerBean implements IConferenceManager {
	@PersistenceContext
    EntityManager em;

	public Conference addConference(String titre, String descirption, String infoComplementray, Date dataAbstract, Date dateArticle, Date dateEvaluation, Date dateStart, Date dateEnd) {
		Conference conf = new Conference(titre, descirption, infoComplementray, dataAbstract, dateArticle, dateEvaluation, dateStart, dateEnd);
		em.persist(conf);
		em.flush();
		return conf;
	}

	public Conference getConference(Integer id) {
		 return em.find(Conference.class, id);
	}

	public void remove(Integer conferenceId) {
		Conference persistedConf = em.find(Conference.class, conferenceId);
		em.remove(persistedConf);
		em.flush();
	}

	public void update(Conference conf) {
		em.merge(conf);
		em.flush();
	}

	@SuppressWarnings("unchecked")
	public List<Conference> getConferences() {
		 return em.createQuery("from Conference conf ORDER BY conf.id").getResultList();
	}
	
	public List<Conference> getConferences(User user){
		List<Conference> list = new ArrayList<Conference>();
		
		List<Role> tmpList = this.getRoles(user);

		Conference conf;
		for (Role role : tmpList) {
			conf = role.getConference();
			list.add(conf);
		}
		return list;
	}
	
			
	/* 
	 * 
	 * m�thodes relatives aux roles
	 * */
	
	public Role addRole(Role.RoleType roleType, String login, Integer confId) {
		User user = em.find(User.class, login);
		Conference conf = em.find(Conference.class, confId);
		Role role = new Role(roleType, user, conf);
		em.persist(role);
		em.flush();
		return role;
	}

	public void removeRole(Role role) {
		em.remove(role);
		em.flush();
	}
	
	public void removePCMemberForConf(Integer confId) {
		Conference conf = em.find(Conference.class, confId);
		Query query = em.createQuery("delete from Role where conference=? and type=?");
		query.setParameter(1, conf);
		query.setParameter(2, RoleType.PCMEMBER);
		query.executeUpdate();
	}

	public void updateRole(Role role){
		em.merge(role);
		em.flush();
	}
	
	@SuppressWarnings("unchecked")
	public List<Role> getRoles(Conference conf){
		Query query = em.createQuery("from Role role where conference = ?");
		query.setParameter(1, conf);		 		
		return query.getResultList();
	}
	
	@SuppressWarnings("unchecked")	
	public List<Role> getRoles(User user) {
		 Query query = em.createQuery("from Role role where user = ?");
		 query.setParameter(1, user); 		
		return query.getResultList();
	} 

	@SuppressWarnings("unchecked")
	public List<Role> getRoles(String userLogin, Integer confId) {
		User user = em.find(User.class, userLogin);
		Conference conf = em.find(Conference.class, confId);
		 Query query = em.createQuery("from Role role where conference = ? and user = ?");
		 query.setParameter(1, conf);
		 query.setParameter(2, user);	
		return query.getResultList();
	}

	public boolean exists(Integer conferenceId) {
		return (this.getConference(conferenceId)!=null);
	}

	/* ================================================ */
	/* = Invitation management methods implementation = */
	/* ================================================ */
	
	public InvitationToken addInvitationToken(String email, RoleType role,
			Integer conferenceId) throws ConferenceDoesntExistException {
		Conference conf = getConference(conferenceId);
		
		if(conf == null){
			throw new ConferenceDoesntExistException(conferenceId);
		}
		

		InvitationTokenPK tokenPK = new InvitationTokenPK();
		tokenPK.email = email;
		tokenPK.role = role;
		tokenPK.conference = conf;
		
		InvitationToken newToken = em.find(InvitationToken.class, tokenPK);
		
		if(newToken == null){
			newToken = new InvitationToken();
			newToken.setEmail(email);
			newToken.setRole(role);
			newToken.setConference(conf);
		
			em.persist(newToken);
		}
		
		return newToken;
	}

	public void removeInvitationToken(InvitationToken token) {
		token = em.find(InvitationToken.class, token.getId());
		em.remove(token);
	}

	public InvitationToken getInvitationToken(InvitationTokenPK tokenId) {
		return em.find(InvitationToken.class, tokenId);
	}

	@SuppressWarnings("unchecked")
	public List<InvitationToken> getInvitationTokensForConference(Integer conferenceId) {
		Conference conf = em.find(Conference.class, conferenceId);
		Query query = em.createQuery("from InvitationToken where conference=?");
		query.setParameter(1, conf);
		return query.getResultList();
	}

	public void addCriterionToConference(Integer conferenceId, String name,
			Integer minRating, Integer maxRating) {
		Conference conf = getConference(conferenceId);
		Criterion criterion = new Criterion(name,minRating,maxRating,conf);
		em.persist(criterion);
	}
	
	public void removeCriterionToConference(Integer conferenceId) {
		Conference conf = em.find(Conference.class, conferenceId);
		Query query = em.createQuery("delete from Criterion where conference=?");
		query.setParameter(1, conf);
		query.executeUpdate();
	}
	
	public void removeOneCriterionToConference(Criterion criterion) {
		em.remove(criterion);
		em.flush();
	}
	

	public void addPCMemberToConference(Integer conferenceId, String userLogin) {
		Conference conf = getConference(conferenceId);
		User member = em.find(User.class, userLogin);
		
		// First checks if the role already exists, if not create it
		RolePK memberRolePK = new RolePK(member,RoleType.PCMEMBER,conf);
		if(em.find(Role.class, memberRolePK)==null){
			Role memberRole = new Role();
			memberRole.setType(RoleType.PCMEMBER);
			memberRole.setUser(member);
			memberRole.setConference(conf);
			em.persist(memberRole);
		}
	}

}
