package org.yacos.core.article;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;

import org.yacos.core.conferences.Conference;
import org.yacos.core.users.User;

@Entity
public class Article implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	private int id;
	private String title;
	private String topic;
	private String URL_article;
	private String mainAuthor;
	private ArrayList<String> secondaryAuthors;
	
	/**
	 * The conference this article has been submitted for
	 */
	@ManyToOne(targetEntity=Conference.class)
	@JoinColumn(name="conference_id",nullable=false)
	private Conference conference;
	
	/**
	 * The referees reviewing this article
	 */
	@ManyToMany(targetEntity=User.class)
	@JoinTable(
		name="articles_referees_map",
		joinColumns=@JoinColumn(name="user_id"),
		inverseJoinColumns=@JoinColumn(name="article_id")
	)
	private Collection<User> referees;
	
	/**
	 * The PC Members responsible for this article evaluation
	 */
	@ManyToMany(targetEntity=User.class)
	@JoinTable(
		name="articles_pcmembers_map",
		joinColumns=@JoinColumn(name="user_id"),
		inverseJoinColumns=@JoinColumn(name="article_id")
	)
	private Collection<User> pcMembers;
	
	@OneToMany(targetEntity=Preference.class,mappedBy="article")
	private Collection<Preference> preferences;
	
	private int state;

	public enum state {
		SUMMARY, FINAL
	};

	public Article() {
		secondaryAuthors = new ArrayList<String>();
	}

	public Article(int reference, String title, String topic,
			String url_article, String mainAuthor,
			List<String> secondaryAuthor, int state) {
		//this.id = reference;
		this.title = title;
		this.topic = topic;
		this.URL_article = url_article;
		this.mainAuthor = mainAuthor;
		if(secondaryAuthor != null){
			this.secondaryAuthors = new ArrayList<String>(secondaryAuthor);
		} else {
			this.secondaryAuthors = new ArrayList<String>();
		}
		this.state = state;
		referees = new ArrayList<User>();
		pcMembers = new ArrayList<User>();
	}

	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getTopic() {
		return topic;
	}

	public void setTopic(String topic) {
		this.topic = topic;
	}

	public String getURL_article() {
		return URL_article;
	}

	public void setURL_article(String url_article) {
		URL_article = url_article;
	}

	public String getMainAuthor() {
		return mainAuthor;
	}

	public void setMainAuthor(String mainAuthor) {
		this.mainAuthor = mainAuthor;
	}

	public ArrayList<String> getSecondaryAuthors() {
		return secondaryAuthors;
	}

	public void setSecondaryAuthors(ArrayList<String> secondaryAuthors) {
		this.secondaryAuthors = secondaryAuthors;
	}

	public int getState() {
		return state;
	}

	public void setState(int state) {
		this.state = state;
	}
	
	@ManyToMany(targetEntity=User.class)
	@JoinTable(
		name="articles_referees_map",
		joinColumns=@JoinColumn(name="user_id"),
		inverseJoinColumns=@JoinColumn(name="article_id")
	)
	public Collection<User> getReferees(){
		return referees;
	}
	
	/**
	 * @param referees the referees to set
	 */
	@ManyToMany(targetEntity=User.class)
	@JoinTable(
		name="articles_referees_map",
		joinColumns=@JoinColumn(name="user_id"),
		inverseJoinColumns=@JoinColumn(name="article_id")
	)
	public void setReferees(Collection<User> referees) {
		this.referees = referees;
	}

	@ManyToMany(targetEntity=User.class)
	@JoinTable(
		name="articles_pcmembers_map",
		joinColumns=@JoinColumn(name="user_id"),
		inverseJoinColumns=@JoinColumn(name="article_id")
	)
	public Collection<User> getPCMembers(){
		return pcMembers;
	}
	@ManyToMany(targetEntity=User.class)
	@JoinTable(
		name="articles_pcmembers_map",
		joinColumns=@JoinColumn(name="user_id"),
		inverseJoinColumns=@JoinColumn(name="article_id")
	)
	public void setPCMembers(Collection<User> pcMembers){
		this.pcMembers = pcMembers;
	}
	
	public void assignToPCMember(User pcMember){
		// TODO : Checking if the User is a pcMember for this conference (not implemented yet)
		//if(pcMember.hasRoleForConference(RoleType.PCmember, this.conference)){
			if(! pcMembers.contains(pcMember)){
				pcMembers.add(pcMember);
			} else {
				//throw new DuplicateAssignationException();
			}
		//}
	}

	public void delegateTo(User referee, User pcMember) {
		if(pcMembers.contains(pcMember)){
			if(! referees.contains(referee)){
				referees.add(referee);
			}
		}
	}
	
	@ManyToOne(targetEntity=Conference.class)
	public Conference getConference(){
		return conference;
	}
	
	@ManyToOne(targetEntity=Conference.class)
	public void setConference(Conference conference){
		this.conference = conference;
	}
	
	/**
	 * @return the preferences
	 */
	@OneToMany(targetEntity=Preference.class,mappedBy="article")
	public Collection<Preference> getPreferences() {
		return preferences;
	}

	/**
	 * @param preferences the preferences to set
	 */
	@OneToMany(targetEntity=Preference.class,mappedBy="article")
	public void setPreferences(Collection<Preference> preferences) {
		this.preferences = preferences;
	}

	public boolean hasMember(){
		return false;
	}
}
