package com.k_int.npdb.datamodel;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.Column;
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.Lob;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;

import com.k_int.aggregator.util.SOLRHelper;
import com.k_int.aggregator.util.SOLRHelper.NVPair;

/**
 * Class Work
 */
@Entity
@Table(name = "WORK")
public class Work {

	private Long id;
	private String externalId;
	private Source source;
	private String name;
	private String description;
	private String genre;
	private String url;
	private String language;
	private List<Character> characters = new ArrayList<Character>();
	private List<Work> relatedWorks = new ArrayList<Work>();
	private List<Role> contributors = new ArrayList<Role>();
	private List<Production> productions = new ArrayList<Production>();

	public Work() {
	};

	/**
	 * Get the value of id
	 * 
	 * @return the value of id
	 */
	@Id
	@Column(name = "ID")
	@GeneratedValue(strategy = GenerationType.AUTO)
	public Long getId() {
		return id;
	}

	/**
	 * Get the value of externalId
	 * 
	 * @return the value of externalId
	 */
	@Column(name = "EXTERNAL_ID")
	public String getExternalId() {
		return externalId;
	}

	/**
	 * Get the value of source
	 * 
	 * @return the value of source
	 */
	@ManyToOne
	@JoinColumn(name = "SOURCE_FK")
	public Source getSource() {
		return source;
	}

	/**
	 * Get the value of name
	 * 
	 * @return the value of name
	 */
	@Column(name = "NAME")
	public String getName() {
		return name;
	}

	/**
	 * Get the value of description
	 * 
	 * @return the value of description
	 */
	@Column(name = "DESCRIPTION")
	@Lob
	public String getDescription() {
		return description;
	}

	/**
	 * Get the value of genre
	 * 
	 * @return the value of genre
	 */
	@Column(name = "GENRE")
	public String getGenre() {
		return genre;
	}

	/**
	 * Get the value of url
	 * 
	 * @return the value of url
	 */
	@Column(name = "URL")
	public String getUrl() {
		return url;
	}

	/**
	 * Get the value of language
	 * 
	 * @return the value of language
	 */
	@Column(name = "LANGUAGE")
	public String getLanguage() {
		return language;
	}

	/**
	 * Get the value of characters
	 * 
	 * @return the value of characters
	 */
	@ManyToMany
	@JoinTable(name = "WORK_CHARACTER", joinColumns = { @JoinColumn(name = "WORK_FK") }, inverseJoinColumns = @JoinColumn(name = "CHARACTER_FK"))
	public List<Character> getCharacters() {
		return characters;
	}

	/**
	 * Get the value of relatedWorks
	 * 
	 * @return the value of relatedWorks
	 */
	@ManyToMany
	@JoinTable(name = "RELATED_WORKS", joinColumns = { @JoinColumn(name = "WORK_FK") }, inverseJoinColumns = @JoinColumn(name = "RELATED_FK"))
	public List<Work> getRelatedWorks() {
		return relatedWorks;
	}

	/**
	 * Get the value of contributors
	 * 
	 * @return the value of contributors
	 */
	@ManyToMany
	@JoinTable(name = "WORK_CONTRIBUTOR", joinColumns = { @JoinColumn(name = "WORK_FK") }, inverseJoinColumns = @JoinColumn(name = "ROLE_FK"))
	public List<Role> getContributors() {
		return contributors;
	}

	@OneToMany(mappedBy = "work")
	public List<Production> getProductions() {
		return productions;
	}

	public void setProductions(List<Production> productions) {
		this.productions = productions;
	}

	public void setContributors(List<Role> contributors) {
		this.contributors = contributors;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public void setExternalId(String externalId) {
		this.externalId = externalId;
	}

	public void setGenre(String genre) {
		this.genre = genre;
	}

	public void setCharacters(List<Character> characters) {
		this.characters = characters;
	}

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

	public void setLanguage(String language) {
		this.language = language;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void setRelatedWorks(List<Work> relatedWorks) {
		this.relatedWorks = relatedWorks;
	}

	public void setSource(Source source) {
		this.source = source;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public List<NVPair> toSOLRIndex() {
		List<NVPair> indexProperties = new ArrayList<NVPair>();
		indexProperties.add(new SOLRHelper.NVPair("internalId", "" + id));
		indexProperties.add(new SOLRHelper.NVPair("source", source.getName()));
		for (Role r : contributors) {
			indexProperties.add(new SOLRHelper.NVPair("person", r
					.getContributor().getName()));
		}
		indexProperties.add(new SOLRHelper.NVPair("identifier", "work_" + id));
		indexProperties.add(new SOLRHelper.NVPair("genre", genre));
		indexProperties.add(new SOLRHelper.NVPair("name", name));
		indexProperties.add(new SOLRHelper.NVPair("type", "work"));
		return indexProperties;
	}

	public static Work lookupOrCreate(org.hibernate.Session session,
			Source source, String externalId, String name)
			throws org.hibernate.HibernateException {
		Work result = null;
		org.hibernate.Query q = session
				.createQuery("select x from com.k_int.npdb.datamodel.Work x where x.externalId = ? and x.source.name = ?");
		q.setString(0, externalId);
		q.setString(1, source.getName());
		result = (Work) q.uniqueResult();
		if (result == null && name != null) {
			q = session
					.createQuery("select x from com.k_int.npdb.datamodel.Work x where x.name = ?");
			q.setString(0, name);
			result = (Work) q.uniqueResult();
		}
		if (result == null) {
			result = new Work();
			result.setExternalId(externalId);
			result.setSource(source);
			session.save(result);
		}
		return result;
	}

}
