package it.micegroup.gestioneferie.pianificazioneferie.entity;

import java.io.Serializable;

import javax.validation.constraints.NotNull;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.JoinColumns;
import javax.persistence.FetchType;
import java.util.Collection;
import java.util.ArrayList;
import javax.persistence.OneToMany;
import javax.persistence.CascadeType;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import lombok.ToString;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonProperty.Access;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.annotation.JsonBackReference;
import javax.persistence.ManyToOne;
import javax.validation.constraints.NotNull;

import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.Getter;
import lombok.AllArgsConstructor;

import javax.persistence.Table;

import org.apache.commons.lang3.StringUtils;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.hibernate.Hibernate;
import java.util.Objects;

import it.micegroup.gestioneferie.pianificazioneferie.entity.DstatiRichAdesionePfKey;

import it.micegroup.gestioneferie.libs.entity.BaseEntity;
import it.micegroup.voila2runtime.utils.EntityUtils;

@NoArgsConstructor

@Getter
@Setter
@Entity
@Table(name = "D_RICH_ADESIONE_PF")
public class DrichAdesionePf extends BaseEntity implements Serializable {

	// Generated SERIAL VERSION UID
	private static final long serialVersionUID = 1311793311L;

	@SuppressWarnings("unused")
	private static final Logger LOGGER = LogManager.getLogger(DrichAdesionePf.class);

	// ATTRIBUTES
	@NotNull

	@Column(name = "SEQU_ID_RICH_ADESIONE_PF", columnDefinition = "NUMBER(15)")
	private Long sequIdRichAdesionePf;
	@NotNull

	@Column(name = "CODI_RICHIESTA_ADESIONE", columnDefinition = "VARCHAR(50)")
	private String codiRichiestaAdesione;
	@NotNull

	@Column(name = "DATA_RICHIESTA_ADESIONE", columnDefinition = "DATE")
	private Date dataRichiestaAdesione;
	@NotNull

	@Column(name = "FK_PIANO_FERIE", columnDefinition = "NUMBER(15)")
	private Long fkPianoFerie;
	@NotNull

	@Column(name = "FK_STATO_RICH_ADESIONE", columnDefinition = "NUMBER(15)")
	private Long fkStatoRichAdesione;
	@NotNull

	@Column(name = "FLAG_ELIMINATO", columnDefinition = "VARCHAR(1)")
	private String flagEliminato;
	@NotNull

	@Column(name = "UTENTE_ULTIMA_MODIFICA", columnDefinition = "VARCHAR(50)")
	private String utenteUltimaModifica;
	@NotNull

	@Column(name = "DATA_ULTIMA_MODIFICA", columnDefinition = "DATE")
	private Date dataUltimaModifica;
	@NotNull

	@Column(name = "DATA_INIZIO_RECORD", columnDefinition = "DATE")
	private Date dataInizioRecord;
	@NotNull

	@Column(name = "DATA_FINE_RECORD", columnDefinition = "DATE")
	private Date dataFineRecord;

	// IMPORTED PARENTS

	// CONSTRUCTORS
	public DrichAdesionePf(String objectKey) {
		super();
		setObjectKey(objectKey);
	}

	public DrichAdesionePf(DrichAdesionePfKey drichAdesionePfKey, Long sequIdRichAdesionePf,
			String codiRichiestaAdesione, Date dataRichiestaAdesione, Long fkPianoFerie, Long fkStatoRichAdesione,
			String flagEliminato, String utenteUltimaModifica, Date dataUltimaModifica, Date dataInizioRecord,
			Date dataFineRecord) {
		super();

		this.drichAdesionePfKey = drichAdesionePfKey;

		this.sequIdRichAdesionePf = sequIdRichAdesionePf;
		this.codiRichiestaAdesione = codiRichiestaAdesione;
		this.dataRichiestaAdesione = dataRichiestaAdesione;
		this.fkPianoFerie = fkPianoFerie;
		this.fkStatoRichAdesione = fkStatoRichAdesione;
		this.flagEliminato = flagEliminato;
		this.utenteUltimaModifica = utenteUltimaModifica;
		this.dataUltimaModifica = dataUltimaModifica;
		this.dataInizioRecord = dataInizioRecord;
		this.dataFineRecord = dataFineRecord;
	}

	// CHILDREN
	@JsonProperty(access = Access.WRITE_ONLY)
	@JsonManagedReference("theDrichAdesionePf")
	@OneToMany(mappedBy = "theDrichAdesionePf", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
	@ToString.Exclude
	private Collection<DesitiRichAdesionePf> theDesitiRichAdesionePf = new ArrayList<>();

	@JsonProperty(access = Access.WRITE_ONLY)
	@JsonManagedReference("theDrichAdesionePf")
	@OneToMany(mappedBy = "theDrichAdesionePf", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
	@ToString.Exclude
	private Collection<DsollecitiPf> theDsollecitiPf = new ArrayList<>();

	// PARENTS
	@NotNull
	@ManyToOne(fetch = FetchType.LAZY)
	@JsonBackReference("theDstatiRichAdesionePf")
	@JsonIgnoreProperties(value = { "hibernateLazyInitializer", "handler" }, allowSetters = true)
	private DstatiRichAdesionePf theDstatiRichAdesionePf;
	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "FK_PIANO_FERIE", referencedColumnName = "SEQU_ID_PIANO_FERIE", nullable = true)
	@JsonBackReference("theDpianiFerie")
	@JsonIgnoreProperties(value = { "hibernateLazyInitializer", "handler" }, allowSetters = true)
	private DpianiFerie theDpianiFerie;

	// GETTER/SETTER
	/**
	 * @return the sequIdRichAdesionePf
	 */
	public Long getSequIdRichAdesionePf() {
		return this.sequIdRichAdesionePf;
	}

	/**
	 * @param sequIdRichAdesionePf to set
	 */
	public void setSequIdRichAdesionePf(Long sequIdRichAdesionePf) {
		this.sequIdRichAdesionePf = sequIdRichAdesionePf;
	}

	/**
	 * @return the codiRichiestaAdesione
	 */
	public String getCodiRichiestaAdesione() {
		return this.codiRichiestaAdesione;
	}

	/**
	 * @param codiRichiestaAdesione to set
	 */
	public void setCodiRichiestaAdesione(String codiRichiestaAdesione) {
		this.codiRichiestaAdesione = codiRichiestaAdesione;
	}

	/**
	 * @return the dataRichiestaAdesione
	 */
	public Date getDataRichiestaAdesione() {
		return this.dataRichiestaAdesione;
	}

	/**
	 * @param dataRichiestaAdesione to set
	 */
	public void setDataRichiestaAdesione(Date dataRichiestaAdesione) {
		this.dataRichiestaAdesione = dataRichiestaAdesione;
	}

	/**
	 * @return the fkPianoFerie
	 */
	public Long getFkPianoFerie() {
		return this.fkPianoFerie;
	}

	/**
	 * @param fkPianoFerie to set
	 */
	public void setFkPianoFerie(Long fkPianoFerie) {
		this.fkPianoFerie = fkPianoFerie;
	}

	/**
	 * @return the fkStatoRichAdesione
	 */
	public Long getFkStatoRichAdesione() {
		return this.fkStatoRichAdesione;
	}

	/**
	 * @param fkStatoRichAdesione to set
	 */
	public void setFkStatoRichAdesione(Long fkStatoRichAdesione) {
		this.fkStatoRichAdesione = fkStatoRichAdesione;
	}

	/**
	 * @return the flagEliminato
	 */
	public String getFlagEliminato() {
		return this.flagEliminato;
	}

	/**
	 * @param flagEliminato to set
	 */
	public void setFlagEliminato(String flagEliminato) {
		this.flagEliminato = flagEliminato;
	}

	/**
	 * @return the utenteUltimaModifica
	 */
	public String getUtenteUltimaModifica() {
		return this.utenteUltimaModifica;
	}

	/**
	 * @param utenteUltimaModifica to set
	 */
	public void setUtenteUltimaModifica(String utenteUltimaModifica) {
		this.utenteUltimaModifica = utenteUltimaModifica;
	}

	/**
	 * @return the dataUltimaModifica
	 */
	public Date getDataUltimaModifica() {
		return this.dataUltimaModifica;
	}

	/**
	 * @param dataUltimaModifica to set
	 */
	public void setDataUltimaModifica(Date dataUltimaModifica) {
		this.dataUltimaModifica = dataUltimaModifica;
	}

	/**
	 * @return the dataInizioRecord
	 */
	public Date getDataInizioRecord() {
		return this.dataInizioRecord;
	}

	/**
	 * @param dataInizioRecord to set
	 */
	public void setDataInizioRecord(Date dataInizioRecord) {
		this.dataInizioRecord = dataInizioRecord;
	}

	/**
	 * @return the dataFineRecord
	 */
	public Date getDataFineRecord() {
		return this.dataFineRecord;
	}

	/**
	 * @param dataFineRecord to set
	 */
	public void setDataFineRecord(Date dataFineRecord) {
		this.dataFineRecord = dataFineRecord;
	}

	// CHILD GETTER/SETTER
	/**
	 * @return the DesitiRichAdesionePf
	 */
	public Collection<DesitiRichAdesionePf> getTheDesitiRichAdesionePf() {
		return theDesitiRichAdesionePf;
	}

	/**
	 * @param aDesitiRichAdesionePfList to set
	 */
	public void setTheDesitiRichAdesionePf(Collection<DesitiRichAdesionePf> aDesitiRichAdesionePfList) {
		theDesitiRichAdesionePf = aDesitiRichAdesionePfList;
	}

	/**
	 * @return the DsollecitiPf
	 */
	public Collection<DsollecitiPf> getTheDsollecitiPf() {
		return theDsollecitiPf;
	}

	/**
	 * @param aDsollecitiPfList to set
	 */
	public void setTheDsollecitiPf(Collection<DsollecitiPf> aDsollecitiPfList) {
		theDsollecitiPf = aDsollecitiPfList;
	}

	/// ADD CHILD
	public void addDesitiRichAdesionePf(DesitiRichAdesionePf desitiRichAdesionePf) {
		theDesitiRichAdesionePf.add(desitiRichAdesionePf);
	}

	public void addDsollecitiPf(DsollecitiPf dsollecitiPf) {
		theDsollecitiPf.add(dsollecitiPf);
	}

	// PARENT GETTER/SETTER
	/**
	 * @return the DstatiRichAdesionePf
	 */
	@JsonProperty(access = Access.WRITE_ONLY)
	public DstatiRichAdesionePf getTheDstatiRichAdesionePf() {
		return theDstatiRichAdesionePf;
	}

	/**
	 * @param aDstatiRichAdesionePfList to set
	 */
	public void setTheDstatiRichAdesionePf(DstatiRichAdesionePf aDstatiRichAdesionePf) {
		theDstatiRichAdesionePf = aDstatiRichAdesionePf;
	}

	/**
	 * @return the DpianiFerie
	 */
	@JsonProperty(access = Access.WRITE_ONLY)
	public DpianiFerie getTheDpianiFerie() {
		return theDpianiFerie;
	}

	/**
	 * @param aDpianiFerieList to set
	 */
	public void setTheDpianiFerie(DpianiFerie aDpianiFerie) {
		theDpianiFerie = aDpianiFerie;
	}

	// PARENT ID GETTER/SETTER
	/**
	 * Return the dstatiRichAdesionePfKey from theDstatiRichAdesionePf.
	 * 
	 * @return dstatiRichAdesionePfKey from theDstatiRichAdesionePf.
	 */
	@JsonProperty
	public DstatiRichAdesionePfKey getDstatiRichAdesionePfKey() {
		// If the parent entity object is null, then return null
		if (getTheDstatiRichAdesionePf() == null) {
			return null;
		}
		// Return requested attribute
		return theDstatiRichAdesionePf.getDstatiRichAdesionePfKey();
	}

	/**
	 * Return the sequIdPianoFerie from theDpianiFerie.
	 * 
	 * @return sequIdPianoFerie from theDpianiFerie.
	 */
	@JsonProperty
	public Long getSequIdPianoFerie() {
		// If the parent entity object is null, then return null
		if (getTheDpianiFerie() == null) {
			return null;
		}
		// Return requested attribute
		return theDpianiFerie.getSequIdPianoFerie();
	}

	// PARENT OBJECT TITLE
	/**
	 * Return the object title of theDstatiRichAdesionePf.
	 * 
	 * @return the object title of theDstatiRichAdesionePf.
	 */
	@JsonProperty
	public String getTheDstatiRichAdesionePfObjectTitle() {
		return getTheDstatiRichAdesionePf() != null ? getTheDstatiRichAdesionePf().getObjectTitle() : null;
	}

	/**
	 * Return the object title of theDpianiFerie.
	 * 
	 * @return the object title of theDpianiFerie.
	 */
	@JsonProperty
	public String getTheDpianiFerieObjectTitle() {
		return getTheDpianiFerie() != null ? getTheDpianiFerie().getObjectTitle() : null;
	}

	// PARENT OBJECT KEY
	/**
	 * Return the object key of theDstatiRichAdesionePf.
	 * 
	 * @return the object key of theDstatiRichAdesionePf.
	 */
	@JsonProperty
	public String getTheDstatiRichAdesionePfObjectKey() {
		return getTheDstatiRichAdesionePf() != null ? getTheDstatiRichAdesionePf().getObjectKey() : null;
	}

	/**
	 * Set object key of theDstatiRichAdesionePf.
	 * 
	 */
	@JsonProperty
	public void setTheDstatiRichAdesionePfObjectKey(String objectKey) {
		if (EntityUtils.isValueChanged(getTheDstatiRichAdesionePfObjectKey(), objectKey, false)) {
			DstatiRichAdesionePf dstatiRichAdesionePf = new DstatiRichAdesionePf();
			dstatiRichAdesionePf.setObjectKey(objectKey);
			setTheDstatiRichAdesionePf(dstatiRichAdesionePf);
		}
	}

	/**
	 * Return the object key of theDpianiFerie.
	 * 
	 * @return the object key of theDpianiFerie.
	 */
	@JsonProperty
	public String getTheDpianiFerieObjectKey() {
		return getTheDpianiFerie() != null ? getTheDpianiFerie().getObjectKey() : null;
	}

	/**
	 * Set object key of theDpianiFerie.
	 * 
	 */
	@JsonProperty
	public void setTheDpianiFerieObjectKey(String objectKey) {
		if (EntityUtils.isValueChanged(getTheDpianiFerieObjectKey(), objectKey, false)) {
			DpianiFerie dpianiFerie = new DpianiFerie();
			dpianiFerie.setObjectKey(objectKey);
			setTheDpianiFerie(dpianiFerie);
		}
	}

	// IMPORTED PARENT OBJECT KEY

	// OPERATIONS

	// OBJECT KEY
	/**
	 * Restituisce l'identificativo della chiave in formato stringa. Ritorna
	 * conveniente nelle selezioni da lista.
	 * 
	 * @return L'identificativo della chiave in formato pk1||pk2||pk3...
	 */
	public String getObjectKey() {
		return getObjectKeyById(getDrichAdesionePfKey());
	}

	public String getObjectKeyById(DrichAdesionePfKey identification) {
		if (identification == null) {
			return null;
		}
		StringBuilder output = new StringBuilder();
		return output.toString();
	}

	/**
	 * Inizializza la parte identificativa del bean in base alla stringa tokenizzata
	 * da "||" fornita in input.
	 * 
	 * @param key L'identificativo della chiave in formato pk1||pk2||pk3...
	 */
	public void setObjectKey(String key) {
		if (key == null || key.trim().length() == 0) {
			return;
		}
		String[] array = StringUtils.splitByWholeSeparatorPreserveAllTokens(key, getRowIdFieldDelimiter());
		int ctr = 0;

		drichAdesionePfKey = new DrichAdesionePfKey();
	}

	// OBJECT TITLE
	public String getObjectTitle() {
		StringBuilder output = new StringBuilder();
		output.append(getCodiRichiestaAdesione());
		return output.toString();
	}

	// COMPOSITE PRIMARY KEY
	@EmbeddedId
	private DrichAdesionePfKey drichAdesionePfKey;

	// GETTER/SETTER CK
	/**
	 * @return the drichAdesionePfKey
	 */
	public DrichAdesionePfKey getDrichAdesionePfKey() {
		return this.drichAdesionePfKey;
	}

	/**
	 * @param drichAdesionePfKey to set
	 */
	public void setDrichAdesionePfKey(DrichAdesionePfKey drichAdesionePfKey) {
		this.drichAdesionePfKey = drichAdesionePfKey;
	}

	// COMPOSITE KEY CLASS

	// PREPERSIST
	public void syncCK() {
		if (drichAdesionePfKey == null) {
			drichAdesionePfKey = new DrichAdesionePfKey();
		}
	}

	@PrePersist
	public void prePersist() {
		syncCK();
	}

	@PreUpdate
	public void PreUpdate() {
		syncCK();
	}

	// Equals / HashCode
	@Override
	public boolean equals(Object o) {
		if (this == o)
			return true;
		if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o))
			return false;
		DrichAdesionePf that = (DrichAdesionePf) o;
		return drichAdesionePfKey != null && Objects.equals(drichAdesionePfKey, that.drichAdesionePfKey);
	}

	@Override
	public int hashCode() {
		return Objects.hash(drichAdesionePfKey);
	}
}
