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

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

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.MappedSuperclass;
import javax.persistence.OneToMany;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElements;

import org.gcube.application.geoportal.model.AccessPolicy;
import org.gcube.application.geoportal.model.Record;
import org.gcube.application.geoportal.model.concessioni.LayerConcessione;
import org.gcube.application.geoportal.model.concessioni.RelazioneScavo;
import org.gcube.application.geoportal.model.gis.SDILayerDescriptor;
import org.gcube.application.geoportal.model.report.ValidationReport;
import org.gcube.application.geoportal.utils.CollectionsUtils;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;

import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

import lombok.Getter;
import lombok.Setter;


@Getter
@Setter
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes({
    @Type(value = OtherContent.class),
    @Type(value = RelazioneScavo.class),
    @Type(value = SDILayerDescriptor.class),
    @Type(value = LayerConcessione.class),
    @Type(value = UploadedImage.class),
    })
public abstract class AssociatedContent {
	
	@Id 
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private long id;
	
	@XmlElement
	private AccessPolicy policy;
	private String licenseID;
	private String titolo;
	private LocalDateTime creationTime;
	
	
	public ValidationReport validateForInsertion() {
		ValidationReport toReturn=new ValidationReport("Associated Content");
		toReturn.checkMandatory(policy, "Politica di accesso");
		toReturn.checkMandatory(licenseID, "Licenza");
		toReturn.checkMandatory(titolo,"Titolo");
		toReturn.checkMandatory(creationTime, "Creation time");
		return toReturn;
	}
	
	
	@ManyToOne
    @JoinColumn(name="record_id", nullable=false)
	private Record record;
	
	@LazyCollection(LazyCollectionOption.FALSE)
	@OneToMany(mappedBy = "associated", cascade = CascadeType.ALL)
	@XmlElements({
        @XmlElement(type=GeoServerContent.class),
        @XmlElement(type=WorkspaceContent.class),
    })
	private List<PersistedContent> actualContent=new ArrayList<>();

//	public void detachContent() {
//		if(actualContent!=null)
//			for(PersistedContent p:actualContent)
//				p.setAssociated(null);
//	}
//
//	public void reattachContent() {
//		if(actualContent!=null)
//			for(PersistedContent p:actualContent)
//				p.setAssociated(this);
//	}
	
//	@Override
//	public int hashCode() {
//		final int prime = 31;
//		int result = 1;
////		result = prime * result + ((actualContent == null) ? 0 : actualContent.hashCode());
//		result = prime * result + CollectionsUtils.hashCode(actualContent);
//		
//		result = prime * result + ((creationTime == null) ? 0 : creationTime.hashCode());
//		result = prime * result + (int) (id ^ (id >>> 32));
//		result = prime * result + ((licenseID == null) ? 0 : licenseID.hashCode());
//		result = prime * result + ((policy == null) ? 0 : policy.hashCode());
//		result = prime * result + ((titolo == null) ? 0 : titolo.hashCode());
//		return result;
//	}
//
//
//
//	@Override
//	public boolean equals(Object obj) {
//		if (this == obj)
//			return true;
//		if (obj == null)
//			return false;
//		if (getClass() != obj.getClass())
//			return false;
//		AssociatedContent other = (AssociatedContent) obj;
////		if (actualContent == null) {
////			if (other.actualContent != null)
////				return false;
////		} else if (!actualContent.equals(other.actualContent))
////			return false;
//		if(!CollectionsUtils.equalsCollections(actualContent, other.actualContent)) return false;
//		
//		if (creationTime == null) {
//			if (other.creationTime != null)
//				return false;
//		} else if (!creationTime.equals(other.creationTime))
//			return false;
//		if (id != other.id)
//			return false;
//		if (licenseID == null) {
//			if (other.licenseID != null)
//				return false;
//		} else if (!licenseID.equals(other.licenseID))
//			return false;
//		if (policy != other.policy)
//			return false;
//		if (titolo == null) {
//			if (other.titolo != null)
//				return false;
//		} else if (!titolo.equals(other.titolo))
//			return false;
//		return true;
//	}



	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append("AssociatedContent [id=");
		builder.append(id);
		if(record!=null) {
			builder.append(", owner-record-id=");
			builder.append(record.getId());
		}else {
			builder.append(", record=");
			builder.append(record);
		}
		builder.append(", policy=");
		builder.append(policy);
		builder.append(", licenseID=");
		builder.append(licenseID);
		builder.append(", titolo=");
		builder.append(titolo);
		builder.append(", creationTime=");
		builder.append(creationTime);
		
		builder.append(", actualContent=");
		builder.append(actualContent);
		builder.append("]");
		return builder.toString();
	}



	
	
}
