package org.gcube.application.geoportal.model.concessioni;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;

import org.gcube.application.geoportal.model.AccessPolicy;
import org.gcube.application.geoportal.model.Record;
import org.gcube.application.geoportal.model.RecordType;
import org.gcube.application.geoportal.model.content.OtherContent;
import org.gcube.application.geoportal.model.content.UploadedImage;
import org.gcube.application.geoportal.model.gis.BBOX;
import org.gcube.application.geoportal.model.report.Check;
import org.gcube.application.geoportal.model.report.ConstraintCheck;
import org.gcube.application.geoportal.model.report.ValidationReport;
import org.gcube.application.geoportal.model.report.ValidationReport.ValidationStatus;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import org.hibernate.annotations.Type;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString(callSuper=true)

@Entity
@DiscriminatorValue("CONCESSIONE")
public class Concessione extends Record{

	
	//Introduzione (descrizione del progetto)
	@Type(type="text")
	private String introduzione;

	//Descrizione del contenuto
	@Type(type="text")
	private String descrizioneContenuto;
	
	//Autori	
	@LazyCollection(LazyCollectionOption.FALSE)
	@ElementCollection(targetClass=String.class)
	private List<String> authors;
	
	//Soggetto che materialmente invia i dati.	
	private String contributore;

	//Indicare il nome del titolare/i dei dati contenuti nel dataset e/o per sue specifiche parti.
	@LazyCollection(LazyCollectionOption.FALSE)
	@ElementCollection(targetClass=String.class)
	private List<String> titolari;
	
	
	private String responsabile;
	private String editore;
	
	@LazyCollection(LazyCollectionOption.FALSE)
	@ElementCollection(targetClass=String.class)
	private List<String> fontiFinanziamento;
	
	//Research Excavation; Archaeology  (valori di default)
	@LazyCollection(LazyCollectionOption.FALSE)
	@ElementCollection(targetClass=String.class)
	private List<String> soggetto;

	
	//Referenze bibliografiche, DOI (se esistenti) di risorse correlate all’indagine in oggetto
	@LazyCollection(LazyCollectionOption.FALSE)
	@ElementCollection(targetClass=String.class)
	private List<String> risorseCorrelate;

	
	private LocalDateTime dataInizioProgetto;
	private LocalDateTime dataFineProgetto;
	
	@LazyCollection(LazyCollectionOption.FALSE)
	@ElementCollection(targetClass=String.class)
	private List<String> titolareLicenza;
	
	@LazyCollection(LazyCollectionOption.FALSE)
	@ElementCollection(targetClass=String.class)
	private List<String> titolareCopyright;
	
	@LazyCollection(LazyCollectionOption.FALSE)
	@ElementCollection(targetClass=String.class)
	private List<String> paroleChiaveLibere;
	
	@LazyCollection(LazyCollectionOption.FALSE)
	@ElementCollection(targetClass=String.class)
	private List<String> paroleChiaveICCD;
	
	
	private Double centroidLat;
	private Double centroidLong;
	
	@LazyCollection(LazyCollectionOption.FALSE)
	@OneToOne(cascade = CascadeType.ALL)	
    private RelazioneScavo relazioneScavo;
	
	@LazyCollection(LazyCollectionOption.FALSE)
	@OneToMany(mappedBy = "record", cascade = CascadeType.ALL)
    private List<UploadedImage> immaginiRappresentative;
	
	@LazyCollection(LazyCollectionOption.FALSE)
	@OneToOne(cascade = CascadeType.ALL)
    private LayerConcessione posizionamentoScavo;
	
	@LazyCollection(LazyCollectionOption.FALSE)
	@OneToMany(mappedBy = "record", cascade = CascadeType.ALL)
    private List<LayerConcessione> pianteFineScavo;
	
	@LazyCollection(LazyCollectionOption.FALSE)
	@OneToMany(mappedBy = "record", cascade = CascadeType.ALL)
	private List<OtherContent> genericContent;
	
	
	public Concessione() {
		super();
		setRecordType(RecordType.CONCESSIONE);
	}
		
	
//	@Override
//	public String asJson() throws JsonProcessingException {
//		// Detaching Content ...		
//		if(relazioneScavo!=null) {
//			relazioneScavo.setRecord(null);
//			relazioneScavo.detachContent();
//		}
//		if(immaginiRappresentative!=null)
//			for(UploadedImage img:immaginiRappresentative) {
//				img.setRecord(null);
//				img.detachContent();
//			}
//		if(posizionamentoScavo!=null) {
//			posizionamentoScavo.setRecord(null);
//			posizionamentoScavo.detachContent();
//		}
//		if(pianteFineScavo!=null)
//			for(LayerConcessione l:pianteFineScavo) {
//				l.setRecord(null);
//				l.detachContent();
//			}
//		if(genericContent!=null)
//			for(OtherContent o:genericContent) {
//				o.setRecord(null);
//				o.detachContent();
//			}
//		
//		try {
//			return super.asJson();
//		}finally {
//			//Reattaching content
//			if(relazioneScavo!=null) {
//				relazioneScavo.setRecord(this);
//				relazioneScavo.reattachContent();
//			}
//			if(immaginiRappresentative!=null)
//				for(UploadedImage img:immaginiRappresentative) {
//					img.setRecord(this);
//					img.reattachContent();
//				}
//			if(posizionamentoScavo!=null) {
//				posizionamentoScavo.setRecord(this);
//				posizionamentoScavo.reattachContent();
//			}
//			if(pianteFineScavo!=null)
//				for(LayerConcessione l:pianteFineScavo) {
//					l.setRecord(this);		
//					l.reattachContent();
//				}
//			if(genericContent!=null)
//				for(OtherContent o:genericContent) {
//					o.setRecord(this);
//					o.reattachContent();
//				}
//		}
//	}
	
	@Override
	public ValidationReport validate() {		
		ValidationReport validator= super.validate();
		
		validator.setObjectName("Concessione");
		
		setPolicy(AccessPolicy.OPEN);
		
		
		
		validator.checkMandatory(authors, "Lista Autori");
//		if(validator.checkMandatory(centroidLat, "Latitudine"))
//			if(centroidLat>90||centroidLat<-90) validator.addMessage(ValidationStatus.ERROR, "Latitudine non valida : "+centroidLat);
//		
//		if(validator.checkMandatory(centroidLong, "Longitudine"))
//			if(centroidLong>180||centroidLong<-180) validator.addMessage(ValidationStatus.ERROR, "Longitudine non valida : "+centroidLong);
		
		validator.checkMandatory(contributore, "Contributore");
		if(validator.checkMandatory(dataFineProgetto, "Data Fine Progetto") &&
				validator.checkMandatory(dataInizioProgetto, "Data Inizio Progetto"))
			if(dataFineProgetto.isBefore(dataInizioProgetto)) validator.addMessage(ValidationStatus.ERROR, "Data Fine Progetto non può esser prima di Data Inizio Progetto.");
		
		validator.checkMandatory(descrizioneContenuto, "Descrizione contenuto");
		validator.checkMandatory(editore, "Editore");
		validator.checkMandatory(fontiFinanziamento, "Fonti Finanaziamento");
		validator.checkMandatory(introduzione, "Introduzione");
		validator.checkMandatory(paroleChiaveICCD, "Parole chiave ICCD");
		validator.checkMandatory(paroleChiaveLibere, "Parole chiave libere");
		
		validator.checkMandatory(responsabile,"Responsabile");
	
		
		
		validator.checkMandatory(titolareCopyright, "Titolare Copyright");
		validator.checkMandatory(titolareLicenza,"Titolare licenza");
		validator.checkMandatory(titolari, "Titolari");
		
		
		
		if(validator.checkMandatory(relazioneScavo, "Relazione scavo")) {
			
			
			
			validator.addChild(relazioneScavo.validateForInsertion());
		}

//		if(immaginiRappresentative!=null)
//		
//			for(UploadedImage img : immaginiRappresentative) {
//				validator.setDefault(img.getSoggetto(),getSoggetto());
//				validator.setDefault(img.getCreationTime(),getCreationTime());
//				validator.setDefault(img.getPolicy(), getPolicy());
//				validator.setDefault(img.getLicenzaID(), getLicenzaID());
//
//				validator.addChild(img.validateForInsertion());
//			}
//		
		
		if(validator.checkMandatory(posizionamentoScavo, "Posizionamento scavo")) {
			
			ValidationReport posReport=posizionamentoScavo.validateForInsertion();
			posReport.setObjectName("Posizionamento scavo");
			validator.addChild(posReport);
		}

		
		if(genericContent!=null)
			for(OtherContent content:genericContent)
				validator.addChild(content.validateForInsertion());
		
		if(validator.checkMandatory(pianteFineScavo,"Piante fine scavo"))
			for(LayerConcessione l:pianteFineScavo) {
				validator.addChild(l.validateForInsertion());
			}
						
				
				
		
		
		return validator;
	}
	
	
	@Override
	public void setDefaults() {		
		super.setDefaults();
		
		setCentroidLat(centroidLat);
		
		setDescrizioneContenuto(ConstraintCheck.defaultFor(getDescrizioneContenuto(), 
				"Relazione di fine scavo e relativo abstract; selezione di immagini rappresentative;"
				+ " posizionamento topografico dell'area indagata, pianta di fine scavo.").evaluate());
		
		
		setSoggetto(ConstraintCheck.defaultFor(soggetto, Arrays.asList(new String[] {"Research Excavation","Archaeology"}))
				.addChecks(Check.collectionSizeMin(2)).evaluate());
		
		setLicenzaID(ConstraintCheck.defaultFor(getLicenzaID(), "CC0-1.0").evaluate());
		
		
		
		if(relazioneScavo!=null) {
			relazioneScavo.setTitolo(ConstraintCheck.defaultFor(relazioneScavo.getTitolo(),getNome()+" relazione di scavo").evaluate());
			relazioneScavo.setSoggetto(ConstraintCheck.defaultFor(relazioneScavo.getSoggetto(),getSoggetto()).evaluate());
			relazioneScavo.setCreationTime(ConstraintCheck.defaultFor(relazioneScavo.getCreationTime(),getCreationTime()).evaluate());
			relazioneScavo.setLicenseID(ConstraintCheck.defaultFor(getLicenzaID(), "CC-BY-4.0").evaluate());
			relazioneScavo.setPolicy(getPolicy());
		}


		if(immaginiRappresentative!=null)
			for(UploadedImage img : immaginiRappresentative) {
				img.setSoggetto(ConstraintCheck.defaultFor(img.getSoggetto(),getSoggetto()).evaluate());
				img.setCreationTime(ConstraintCheck.defaultFor(img.getCreationTime(),getCreationTime()).evaluate());
				img.setPolicy(ConstraintCheck.defaultFor(img.getPolicy(),getPolicy()).evaluate());
				img.setLicenseID(ConstraintCheck.defaultFor(img.getLicenseID(),"CC-BY-4.0").evaluate());				
			}
		
		
		if(posizionamentoScavo!=null) {
			posizionamentoScavo.setTitolo(ConstraintCheck.defaultFor(posizionamentoScavo.getTitolo(), getNome()+" posizionamento scavo").evaluate());
			posizionamentoScavo.setAbstractSection(
					ConstraintCheck.defaultFor(posizionamentoScavo.getAbstractSection(),"Posizionamento topografico georeferenziato dell’area interessata dalle indagini").evaluate());
			
			posizionamentoScavo.setTopicCategory(ConstraintCheck.defaultFor(posizionamentoScavo.getTopicCategory(), "Society").evaluate());
			posizionamentoScavo.setSubTopic(ConstraintCheck.defaultFor(posizionamentoScavo.getSubTopic(), "Archeology").evaluate());

			posizionamentoScavo.setParoleChiaveLibere(ConstraintCheck.defaultFor(posizionamentoScavo.getParoleChiaveLibere(),getParoleChiaveLibere()).evaluate());
			posizionamentoScavo.setParoleChiaveICCD(ConstraintCheck.defaultFor(posizionamentoScavo.getParoleChiaveICCD(),getParoleChiaveICCD()).evaluate());
			
			//TODO Evaluate
			posizionamentoScavo.setBbox(ConstraintCheck.defaultFor(posizionamentoScavo.getBbox(), BBOX.WORLD_EXTENT).evaluate());
			
			posizionamentoScavo.setPolicy(ConstraintCheck.defaultFor(posizionamentoScavo.getPolicy(),getPolicy()).evaluate());;
			posizionamentoScavo.setLicenseID(ConstraintCheck.defaultFor(posizionamentoScavo.getLicenseID(), "CC-BY-4.0").evaluate());
			posizionamentoScavo.setResponsabile(getResponsabile());
			posizionamentoScavo.setCreationTime(ConstraintCheck.defaultFor(posizionamentoScavo.getCreationTime(), getCreationTime()).evaluate());
			
			
		}

		
		
		if(pianteFineScavo!=null)
			for(LayerConcessione l:pianteFineScavo) {
				
				l.setTitolo(ConstraintCheck.defaultFor(l.getTitolo(), getNome()+" pianta fine scavo").evaluate());
				l.setAbstractSection(
						ConstraintCheck.defaultFor(l.getAbstractSection(),"Planimetria georeferenziata dell'area indagata al termine delle attività").evaluate());
				
				l.setTopicCategory(ConstraintCheck.defaultFor(l.getTopicCategory(), "Society").evaluate());
				l.setSubTopic(ConstraintCheck.defaultFor(l.getSubTopic(), "Archeology").evaluate());

				l.setParoleChiaveLibere(ConstraintCheck.defaultFor(l.getParoleChiaveLibere(),getParoleChiaveLibere()).evaluate());
				l.setParoleChiaveICCD(ConstraintCheck.defaultFor(l.getParoleChiaveICCD(),getParoleChiaveICCD()).evaluate());
				
				//TODO Evaluate
				l.setBbox(ConstraintCheck.defaultFor(l.getBbox(), BBOX.WORLD_EXTENT).evaluate());
				
				l.setPolicy(ConstraintCheck.defaultFor(l.getPolicy(),getPolicy()).evaluate());;
				l.setLicenseID(ConstraintCheck.defaultFor(l.getLicenseID(), "CC-BY-4.0").evaluate());
				l.setResponsabile(getResponsabile());
				l.setCreationTime(ConstraintCheck.defaultFor(l.getCreationTime(), getCreationTime()).evaluate());
			}
						
		
		
		
	}
	

	
	
}
