/**
 * 
 */
package de.bstly.board.model;

import java.time.Instant;
import java.util.List;
import java.util.Map;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.hibernate.search.engine.backend.types.Projectable;
import org.hibernate.search.engine.backend.types.Searchable;
import org.hibernate.search.engine.backend.types.Sortable;
import org.hibernate.search.mapper.pojo.bridge.mapping.annotation.ValueBridgeRef;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.DocumentId;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.FullTextField;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.Indexed;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.KeywordField;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import com.google.common.collect.Maps;

import de.bstly.board.model.support.EntryStatus;
import de.bstly.board.model.support.EntryType;
import de.bstly.board.model.support.FlaggedStatus;
import de.bstly.board.model.support.InstantValueBridge;
import de.bstly.board.model.support.Types;

/**
 * The Class Entry.
 */
@Entity
@Table(name = "entries")
@EntityListeners({ AuditingEntityListener.class })
@Indexed
public class Entry {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column(name = "id", nullable = false)
	@DocumentId
	private Long id;
	@Column(name = "author", nullable = false)
	private String author;
	@Column(name = "created", nullable = false)
	@KeywordField(name = "created", valueBridge = @ValueBridgeRef(type = InstantValueBridge.class), projectable = Projectable.YES, sortable = Sortable.YES)
	private Instant created;
	@Enumerated(EnumType.STRING)
	@Column(name = "entry_type", nullable = false)
	private EntryType entryType;
	@Enumerated(EnumType.STRING)
	@Column(name = "entry_status", nullable = false, columnDefinition = "varchar(255) default 'NORMAL'")
	private EntryStatus entryStatus;
	@Enumerated(EnumType.STRING)
	@Column(name = "flagged_status", nullable = false, columnDefinition = "varchar(255) default 'NORMAL'")
	private FlaggedStatus flaggedStatus;
	@Column(name = "url")
	private String url;
	@Column(name = "title", nullable = false)
	@FullTextField(name = "title", searchable = Searchable.YES, analyzer = "english")
	@FullTextField(name = "title_de", searchable = Searchable.YES, analyzer = "german")
	private String title;
	@Lob
	@Column(name = "text")
	@FullTextField(name = "text", searchable = Searchable.YES, analyzer = "english")
	@FullTextField(name = "text_de", searchable = Searchable.YES, analyzer = "german")
	private String text;
	@Transient
	private List<String> tags;
	@Transient
	private Float ranking;
	@Transient
	private Long points;
	@Transient
	private Map<String, Object> metadata;
	@Transient
	private final Types type = Types.entry;

	/**
	 * Gets the id.
	 *
	 * @return the id
	 */
	public Long getId() {
		return id;
	}

	/**
	 * Sets the id.
	 *
	 * @param id the new id
	 */
	public void setId(Long id) {
		this.id = id;
	}

	/**
	 * Gets the author.
	 *
	 * @return the author
	 */
	public String getAuthor() {
		return author;
	}

	/**
	 * Sets the author.
	 *
	 * @param author the new author
	 */
	public void setAuthor(String author) {
		this.author = author;
	}

	/**
	 * Gets the created.
	 *
	 * @return the created
	 */
	public Instant getCreated() {
		return created;
	}

	/**
	 * Sets the created.
	 *
	 * @param created the new created
	 */
	public void setCreated(Instant created) {
		this.created = created;
	}

	/**
	 * Gets the entry type.
	 *
	 * @return the entry type
	 */
	public EntryType getEntryType() {
		return entryType;
	}

	/**
	 * Sets the entry type.
	 *
	 * @param entryType the new entry type
	 */
	public void setEntryType(EntryType entryType) {
		this.entryType = entryType;
	}

	/**
	 * Gets the entry status.
	 *
	 * @return the entry status
	 */
	public EntryStatus getEntryStatus() {
		return entryStatus;
	}

	/**
	 * Sets the entry status.
	 *
	 * @param entryStatus the new entry status
	 */
	public void setEntryStatus(EntryStatus entryStatus) {
		this.entryStatus = entryStatus;
	}

	/**
	 * Gets the flagged status.
	 *
	 * @return the flagged status
	 */
	public FlaggedStatus getFlaggedStatus() {
		return flaggedStatus;
	}

	/**
	 * Sets the flagged status.
	 *
	 * @param flaggedStatus the new flagged status
	 */
	public void setFlaggedStatus(FlaggedStatus flaggedStatus) {
		this.flaggedStatus = flaggedStatus;
	}

	/**
	 * Gets the url.
	 *
	 * @return the url
	 */
	public String getUrl() {
		return url;
	}

	/**
	 * Sets the url.
	 *
	 * @param url the new url
	 */
	public void setUrl(String url) {
		this.url = url;
	}

	/**
	 * Gets the title.
	 *
	 * @return the title
	 */
	public String getTitle() {
		return title;
	}

	/**
	 * Sets the title.
	 *
	 * @param title the new title
	 */
	public void setTitle(String title) {
		this.title = title;
	}

	/**
	 * Gets the text.
	 *
	 * @return the text
	 */
	public String getText() {
		return text;
	}

	/**
	 * Sets the text.
	 *
	 * @param text the new text
	 */
	public void setText(String text) {
		this.text = text;
	}

	/**
	 * Gets the tags.
	 *
	 * @return the tags
	 */
	public List<String> getTags() {
		return tags;
	}

	/**
	 * Sets the tags.
	 *
	 * @param tags the new tags
	 */
	public void setTags(List<String> tags) {
		this.tags = tags;
	}

	/**
	 * Gets the ranking.
	 *
	 * @return the ranking
	 */
	public Float getRanking() {
		return ranking;
	}

	/**
	 * Sets the ranking.
	 *
	 * @param ranking the new ranking
	 */
	public void setRanking(Float ranking) {
		this.ranking = ranking;
	}

	/**
	 * Gets the points.
	 *
	 * @return the points
	 */
	public Long getPoints() {
		return points;
	}

	/**
	 * Sets the points.
	 *
	 * @param points the new points
	 */
	public void setPoints(Long points) {
		this.points = points;
	}

	/**
	 * Gets the metadata.
	 *
	 * @return the metadata
	 */
	public Map<String, Object> getMetadata() {
		if (metadata == null) {
			metadata = Maps.newHashMap();
		}
		return metadata;
	}

	/**
	 * Sets the metadata.
	 *
	 * @param metadata the metadata
	 */
	public void setMetadata(Map<String, Object> metadata) {
		this.metadata = metadata;
	}

	/**
	 * @return the type
	 */
	public Types getType() {
		return type;
	}

}
