package com.k_int.npdb.datamodel;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
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.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.k_int.aggregator.util.SOLRHelper;
import com.k_int.aggregator.util.SOLRHelper.NVPair;
import com.k_int.npdb.service.TheatreWebHandler;

/**
 * Class Performance
 */
@Entity
@Table(name = "PERFORMANCE")
public class Performance {

	private Long id;
	private String externalId;
	private Source source;
	private int numberOfPerformance;
	private Venue venue;
	private Production production;
	private List<Season> seasons = new ArrayList<Season>();
	private List<Event> events = new ArrayList<Event>();
	private String language;
	private String note;
	private Date from;
	private Date to;
	private Date openingNight;
	private List<Role> contributors = new ArrayList<Role>();
	
	private static Log log = LogFactory.getLog(Performance.class);


	private static SimpleDateFormat sdfSOLR = new SimpleDateFormat(
			"yyyy-MM-dd'T'HH:mm:ss'Z'");

	public Performance() {
	};

	/**
	 * 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 numberOfPerformance
	 * 
	 * @return the value of numberOfPerformance
	 */
	@Column(name = "NUMBER_OF_PERFORMANCE")
	public int getNumberOfPerformance() {
		return numberOfPerformance;
	}

	/**
	 * Get the value of venue
	 * 
	 * @return the value of venue
	 */
	@ManyToOne
	@JoinColumn(name = "VENUE_FK")
	public Venue getVenue() {
		return venue;
	}

	/**
	 * Get the value of production
	 * 
	 * @return the value of production
	 */
	@ManyToOne
	@JoinColumn(name = "PRODUCTION_FK")
	public Production getProduction() {
		return production;
	}

	/**
	 * Get the value of season
	 * 
	 * @return the value of season
	 */
	@ManyToMany
	@JoinTable(name = "PERFORMANCE_SEASON", joinColumns = { @JoinColumn(name = "PERFORMANCE_FK") }, inverseJoinColumns = @JoinColumn(name = "SEASON_FK"))
	public List<Season> getSeasons() {
		return seasons;
	}

	/**
	 * Get the value of event
	 * 
	 * @return the value of event
	 */
	@ManyToMany
	@JoinTable(name = "PERFORMANCE_EVENT", joinColumns = { @JoinColumn(name = "PERFORMANCE_FK") }, inverseJoinColumns = @JoinColumn(name = "EVENT_FK"))
	public List<Event> getEvents() {
		return events;
	}

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

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

	@Column(name = "FROM_DATE", columnDefinition = "date")
	public Date getFrom() {
		return from;
	}

	@Column(name = "NOTE")
	public String getNote() {
		return note;
	}

	@Column(name = "OPENING_NIGHT", columnDefinition = "date")
	public Date getOpeningNight() {
		return openingNight;
	}

	@Column(name = "TO_DATE", columnDefinition = "date")
	public Date getTo() {
		return to;
	}

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

	public void setEvents(List<Event> events) {
		this.events = events;
	}

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

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

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

	public void setNumberOfPerformance(int numberOfPerformance) {
		this.numberOfPerformance = numberOfPerformance;
	}

	public void setProduction(Production production) {
		this.production = production;
	}

	public void setSeasons(List<Season> seasons) {
		this.seasons = seasons;
	}

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

	public void setVenue(Venue venue) {
		this.venue = venue;
	}

	public void setFrom(Date from) {
		this.from = from;
	}

	public void setNote(String note) {
		this.note = note;
	}

	public void setOpeningNight(Date openingNight) {
		this.openingNight = openingNight;
	}

	public void setTo(Date to) {
		this.to = to;
	}

	public List<NVPair> toSOLRIndex() {
		List<NVPair> indexProperties = new ArrayList<NVPair>();
		String displayName = displayName();
		if (displayName != null && !"".equals(displayName)) {

			indexProperties.add(new SOLRHelper.NVPair("internalId", "" + id));
			indexProperties.add(new SOLRHelper.NVPair("source", source
					.getName()));

			if (from != null)
				indexProperties.add(new SOLRHelper.NVPair("from", sdfSOLR
						.format(from)));
			if (to != null)
				indexProperties.add(new SOLRHelper.NVPair("to", sdfSOLR
						.format(to)));
			for (Role r : contributors) {
				indexProperties.add(new SOLRHelper.NVPair("person", r
						.getContributor().getName()));
			}
			indexProperties.add(new SOLRHelper.NVPair("identifier",
					"performance_" + id));
			indexProperties.add(new SOLRHelper.NVPair("name", displayName));
			indexProperties
					.add(new SOLRHelper.NVPair("venue", venue.getName()));
			indexProperties.add(new SOLRHelper.NVPair("type", "performance"));
		}
		return indexProperties;
	}

	public String displayName() {
		String nameOfVenue = (venue != null && venue.getName() != null) ? " at "
				+ venue.getName()
				: "";
		return production.displayName() + nameOfVenue;
	}

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

}
