package org.gcube.application.geoportal.managers;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import org.gcube.application.geoportal.model.InputStreamDescriptor;
import org.gcube.application.geoportal.model.concessioni.Concessione;
import org.gcube.application.geoportal.model.concessioni.LayerConcessione;
import org.gcube.application.geoportal.model.concessioni.RelazioneScavo;
import org.gcube.application.geoportal.model.content.AssociatedContent;
import org.gcube.application.geoportal.model.content.GeoServerContent;
import org.gcube.application.geoportal.model.content.PersistedContent;
import org.gcube.application.geoportal.model.content.UploadedImage;
import org.gcube.application.geoportal.model.content.WorkspaceContent;
import org.gcube.application.geoportal.model.db.DBConstants;
import org.gcube.application.geoportal.model.db.PostgisTable;
import org.gcube.application.geoportal.model.fault.SDIInteractionException;
import org.gcube.application.geoportal.storage.ContentHandler;
import org.gcube.application.geoportal.storage.SDIManager;
import org.gcube.application.geoportal.storage.WorkspaceManager;
import org.gcube.application.geoportal.utils.Serialization;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class ConcessioneManager extends AbstractRecordManager<Concessione> {

	protected ConcessioneManager(Concessione theRecord) {
		super(theRecord);
	}
	@Override
	protected PostgisTable getCentroidsTable() {
		return DBConstants.Concessioni.CENTROIDS;
	}

	@Override
	protected void postcommit() {
		transaction.begin();
		log.debug("Updating references.. ");
		if(getRecord().getImmaginiRappresentative()!=null)
			for(UploadedImage img:getRecord().getImmaginiRappresentative()) {
				entityManager.createNativeQuery("Update uploadedimage set record_id="+getRecord().getId()+" where id = "+img.getId()).executeUpdate();			
			}
		if(getRecord().getPianteFineScavo()!=null)
			for(LayerConcessione l:getRecord().getPianteFineScavo()) {
				entityManager.createNativeQuery("Update layerconcessione set record_id="+getRecord().getId()+" where id = "+l.getId()).executeUpdate();
				if(l.getWmsLink()!=null) {
					entityManager.createNativeQuery("Update layerconcessione set wmslink='"+l.getWmsLink()+"' where id = "+l.getId()).executeUpdate();
//					entityManager.createNativeQuery("Update sdilayerdescriptor set wmslink='"+l.getWMSLink()+"' where id = "+l.getId()).executeUpdate();
				}
				if(l.getLayerName()!=null) {
					entityManager.createNativeQuery("Update layerconcessione set layername='"+l.getLayerName()+"' where id = "+l.getId()).executeUpdate();
//					entityManager.createNativeQuery("Update sdilayerdescriptor set layername='"+l.getLayerName()+"' where id = "+l.getId()).executeUpdate();
				}
				if(l.getLayerID()!=null) {
					entityManager.createNativeQuery("Update layerconcessione set layerid='"+l.getLayerID()+"' where id = "+l.getId()).executeUpdate();
//					entityManager.createNativeQuery("Update sdilayerdescriptor set layerid='"+l.getLayerID()+"' where id = "+l.getId()).executeUpdate();
				}
				if(l.getLayerUUID()!=null) {
					entityManager.createNativeQuery("Update layerconcessione set layeruuid='"+l.getLayerUUID()+"' where id = "+l.getId()).executeUpdate();
//					entityManager.createNativeQuery("Update sdilayerdescriptor set layeruuid='"+l.getLayerUUID()+"' where id = "+l.getId()).executeUpdate();
				}
			}
		if(getRecord().getPosizionamentoScavo()!=null) {
			LayerConcessione l=getRecord().getPosizionamentoScavo();
//			entityManager.createNativeQuery("Update layerconcessione set record_id="+getRecord().getId()+" where id = "+l.getId()).executeUpdate();
			if(l.getWmsLink()!=null) {
				entityManager.createNativeQuery("Update layerconcessione set wmslink='"+l.getWmsLink()+"' where id = "+l.getId()).executeUpdate();
//				entityManager.createNativeQuery("Update sdilayerdescriptor set wmslink='"+l.getWMSLink()+"' where id = "+l.getId()).executeUpdate();
			}
			if(l.getLayerName()!=null) {
				entityManager.createNativeQuery("Update layerconcessione set layername='"+l.getLayerName()+"' where id = "+l.getId()).executeUpdate();
//				entityManager.createNativeQuery("Update sdilayerdescriptor set layername='"+l.getLayerName()+"' where id = "+l.getId()).executeUpdate();
			}
			if(l.getLayerID()!=null) {
				entityManager.createNativeQuery("Update layerconcessione set layerid='"+l.getLayerID()+"' where id = "+l.getId()).executeUpdate();
//				entityManager.createNativeQuery("Update sdilayerdescriptor set layerid='"+l.getLayerID()+"' where id = "+l.getId()).executeUpdate();
			}
			if(l.getLayerUUID()!=null) {
				entityManager.createNativeQuery("Update layerconcessione set layeruuid='"+l.getLayerUUID()+"' where id = "+l.getId()).executeUpdate();
//				entityManager.createNativeQuery("Update sdilayerdescriptor set layeruuid='"+l.getLayerUUID()+"' where id = "+l.getId()).executeUpdate();
			}
		}
		
		if(getRecord().getCentroidLat()!=null) {
			entityManager.createNativeQuery(
					String.format("Update concessione set centroidlat=%1$f where id=%2$d", getRecord().getCentroidLat(),getRecord().getId())).executeUpdate();
		}
		if(getRecord().getCentroidLong()!=null) {
			entityManager.createNativeQuery(
					String.format("Update concessione set centroidlong=%1$f where id=%2$d", getRecord().getCentroidLong(),getRecord().getId())).executeUpdate();
		}
		transaction.commit();
	}
	
//	private void updateReferences(AssociatedContent c) {
//		for(PersistedContent p:c.getActualContent()) {
//			String query=null;
//			if(p instanceof GeoServerContent) {
//				query="";
//			}else if (p instanceof WorkspaceContent) {
//				query="";
//			}
//			query=String.format("Update %1$s set ", args)
//			entityManager.createNativeQuery("Update ")
//		}
//	}
	
	
	@Override
	protected void initCentroidLayer() throws SDIInteractionException {
		log.debug("Checking for centroid layer configuration.. ");
		SDIManager sdiManager=new SDIManager();

		sdiManager.configureCentroidLayer("centroids_concessioni", "gna", "gna_postgis");
	}

	public Concessione setRelazioneScavo(RelazioneScavo rel, InputStreamDescriptor theFile) throws IOException {
		ContentHandler handler=getContentHandler();
		//Check if already stored content
		Concessione record=getRecord();
		if(record.getRelazioneScavo()!=null && !record.getRelazioneScavo().getActualContent().isEmpty()) {
			handler.disposeQuietly(record.getRelazioneScavo());
		}

		rel.setRecord(record);

		//Register relazione
		record.setRelazioneScavo(rel);
		handler.register(rel, theFile);

		return record;
	}

	public Concessione addImmagineRappresentativa(UploadedImage img, InputStreamDescriptor theFile) throws IOException {
		ContentHandler handler=getContentHandler();
		Concessione record=getRecord();
		//Add immagine

		img.setRecord(record);
		if(record.getImmaginiRappresentative()==null)
			record.setImmaginiRappresentative(new ArrayList<UploadedImage>());
		record.getImmaginiRappresentative().add(img);
		handler.register(img, theFile);

		return record;
	}

	//	public Concessione disposeImmagineRappresentativa(UploadedImage img, InputStream theFile) {
	//		if(concessione.)
	//	}

	public Concessione setPosizionamento(LayerConcessione layer, InputStreamDescriptor...inputStreams ) throws IOException {
		ContentHandler handler=getContentHandler();
		//Check if already stored content
		Concessione record=getRecord();
		if(record.getPosizionamentoScavo()!=null && !record.getPosizionamentoScavo().getActualContent().isEmpty())
			handler.disposeQuietly(record.getPosizionamentoScavo());

		layer.setRecord(record);

		//Register posizionamneot
		record.setPosizionamentoScavo(layer);
		handler.register(layer, inputStreams);

		return record;
	}

	public Concessione addPiantaFineScavo(LayerConcessione layer, InputStreamDescriptor...inputStreams ) throws IOException {
		ContentHandler handler=getContentHandler();
		Concessione record=getRecord();
		//Add pianta
		layer.setRecord(record);

		if(record.getPianteFineScavo()==null)
			record.setPianteFineScavo(new ArrayList<LayerConcessione>());
		record.getPianteFineScavo().add(layer);
		handler.register(layer, inputStreams);

		return record;
	}



	@Override
	protected void onDelete() {
		log.debug("Deleting content for record "+getRecord());

		ContentHandler<Concessione> handler=getContentHandler();
		Concessione c=getRecord();		
		handler.disposeQuietly(c.getRelazioneScavo());
		handler.disposeQuietly(c.getPosizionamentoScavo());
		if(c.getImmaginiRappresentative()!=null)
			for(UploadedImage img:c.getImmaginiRappresentative())
				handler.disposeQuietly(img);

		if(c.getPianteFineScavo()!=null)
			for(LayerConcessione l:c.getPianteFineScavo())
				handler.disposeQuietly(l);

		log.debug("Clearing folder.. ");
		try {
			new WorkspaceManager(getRecord()).getWSBase().forceDelete();
		}catch(Exception e) {
			log.warn("Unable to delete base folder ",e);
		}
	}



	@Override
	protected Map<String,String> evaluateCentroid(){

		Concessione record=getRecord();

		// CENTROID 
		Map<String,String> centroidsRow=new HashMap<String, String>();
		centroidsRow.put(DBConstants.Concessioni.PRODUCT_ID, record.getId()+"");		
		centroidsRow.put(DBConstants.Concessioni.ANNO, record.getDataInizioProgetto().getYear()+"");
		centroidsRow.put(DBConstants.Concessioni.NOME, record.getNome());
		centroidsRow.put(DBConstants.Concessioni.REGIONE, ""); //TODO 
		
		
		
		if(record.getCentroidLat()==null||record.getCentroidLat()==0)
		try {
			log.debug("Evaluating Centroid latitude for record "+record);
			record.setCentroidLat((record.getPosizionamentoScavo().getBbox().getMaxLat()+
					record.getPosizionamentoScavo().getBbox().getMinLat())/2);
		}catch (Throwable t) {
			log.warn("Unable to evaluate centroid latitude "+t);
		}
		
		if(record.getCentroidLong()==null||record.getCentroidLong()==0)
			try {
				log.debug("Evaluating Centroid Longituted for record "+record);
				record.setCentroidLong((record.getPosizionamentoScavo().getBbox().getMaxLong()+
						record.getPosizionamentoScavo().getBbox().getMinLong())/2);
			}catch (Throwable t) {
				log.warn("Unable to evaluate centroid latitude "+t);
			}
		
		
		centroidsRow.put(DBConstants.Defaults.XCOORD_FIELD, record.getCentroidLong()+"");
		centroidsRow.put(DBConstants.Defaults.YCOORD_FIELD, record.getCentroidLat()+"");

		//Updated Schema 
		centroidsRow.put(DBConstants.Concessioni.DESCRIZIONE,record.getIntroduzione());
		centroidsRow.put(DBConstants.Concessioni.CONTENUTO,record.getDescrizioneContenuto());
		centroidsRow.put(DBConstants.Concessioni.AUTORE,Serialization.asString(record.getAuthors()));
		centroidsRow.put(DBConstants.Concessioni.CONTRIBUTORE,record.getContributore());
		centroidsRow.put(DBConstants.Concessioni.TITOLARE,Serialization.asString(record.getTitolari()));
		centroidsRow.put(DBConstants.Concessioni.RESPONSABILE,record.getResponsabile());
		centroidsRow.put(DBConstants.Concessioni.EDITORE,record.getEditore());
		centroidsRow.put(DBConstants.Concessioni.FINANZIAMENTO,Serialization.asString(record.getFontiFinanziamento()));
		centroidsRow.put(DBConstants.Concessioni.SOGGETTO,Serialization.asString(record.getSoggetto()));
		centroidsRow.put(DBConstants.Concessioni.RISORSE,Serialization.asString(record.getRisorseCorrelate()));
		centroidsRow.put(DBConstants.Concessioni.DATE_SCAVO,Serialization.FULL_FORMATTER.format(record.getDataFineProgetto()));
		centroidsRow.put(DBConstants.Concessioni.DATA_ARCHIVIAZIONE,Serialization.FULL_FORMATTER.format(record.getLastUpdateTime()));
		centroidsRow.put(DBConstants.Concessioni.VERSIONE,record.getVersion());
		centroidsRow.put(DBConstants.Concessioni.LICENZA,record.getLicenzaID());
		centroidsRow.put(DBConstants.Concessioni.TITOLARE_LICENZA,Serialization.asString(record.getTitolareLicenza()));
		centroidsRow.put(DBConstants.Concessioni.ACCESSO,record.getPolicy().toString());
		centroidsRow.put(DBConstants.Concessioni.PAROLE_CHIAVE,Serialization.asString(record.getParoleChiaveLibere()));

		return centroidsRow;
	}
}
