package org.yacos.core.article;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
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.evaluation.Report;
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;
	
	@ManyToOne(targetEntity=Conference.class)
	@JoinColumn(name="mainAuthor",nullable=false)
	private User 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;
	
	@OneToMany(cascade=CascadeType.ALL, targetEntity=Delegation.class, mappedBy="article")
	private List<Delegation> delegation;
	
	/**
	 * 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 List<User> pcMembers;
	
	@OneToMany(targetEntity=Preference.class,mappedBy="article", cascade=CascadeType.ALL)
	private List<Preference> preferences;

	@OneToMany(targetEntity=Report.class, mappedBy="article", cascade=CascadeType.ALL)
	private List<Report> report;
	
	
	public enum State {
		SUMMARY, FINAL , REJECTED, ACCEPTED
	};
	@Enumerated(EnumType.ORDINAL)
	private State state;

  

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

	public Article(String title, String topic,
			String url_article, User mainAuthor,
			List<String> secondaryAuthor, State state, Conference conference) {
		//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;
		pcMembers = new ArrayList<User>();
		this.conference = conference;
	}

	@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;
	}

	@ManyToOne(targetEntity=User.class)
	@JoinColumn(name="mainAuthor",nullable=false)
	public User getMainAuthor() {
		return mainAuthor;
	}

	@ManyToOne(targetEntity=User.class)
	@JoinColumn(name="mainAuthor",nullable=false)
	public void setMainAuthor(User mainAuthor) {
		this.mainAuthor = mainAuthor;
	}

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

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

	@Enumerated(EnumType.ORDINAL)
	public State getState() {
		return state;
	}

	@Enumerated(EnumType.ORDINAL)
	public void setState(State state) {
		this.state=state;
	}
		
	@ManyToMany(targetEntity=User.class)
	@JoinTable(
		name="articles_pcmembers_map",
		joinColumns=@JoinColumn(name="user_id"),
		inverseJoinColumns=@JoinColumn(name="article_id")
	)
	public List<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(List<User> pcMembers) {
		this.pcMembers = pcMembers;
	}
//	public void addPCMember(User pcMember){
//		if(! pcMembers.contains(pcMember)){
//			pcMembers.add(pcMember);
//		}
//	}
//	
//	public void removePCMember(User pcMember){
//		if(pcMembers.contains(pcMember)){
//			pcMembers.remove(pcMember);
//		}
//	}

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

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

	public boolean hasMember(){
		return false;
	}
	
	@OneToMany(targetEntity=Report.class, mappedBy="article", cascade=CascadeType.ALL)
	public List<Report> getReport() {
		return report;
	}
	@OneToMany(targetEntity=Report.class, mappedBy="article", cascade=CascadeType.ALL)
	public void setReport(List<Report> report) {
		this.report = report;
	}

	@OneToMany(cascade=CascadeType.ALL, targetEntity=Delegation.class, mappedBy="article")
	public List<Delegation> getDelegation() {
		return delegation;
	}

	@OneToMany(cascade=CascadeType.ALL, targetEntity=Delegation.class, mappedBy="article")
	public void setDelegation(List<Delegation> delegation) {
		this.delegation = delegation;
	}
	
	
}
