package org.gcube.application.geoportal;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import org.gcube.application.geoportal.managers.AbstractRecordManager;
import org.gcube.application.geoportal.managers.ConcessioneManager;
import org.gcube.application.geoportal.managers.ManagerFactory;
import org.gcube.application.geoportal.model.InputStreamDescriptor;
import org.gcube.application.geoportal.model.Record;
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.UploadedImage;
import org.gcube.application.geoportal.model.fault.PersistenceException;
import org.gcube.application.geoportal.model.fault.PublishException;
import org.gcube.application.geoportal.model.fault.ValidationException;
import org.gcube.application.geoportal.model.report.ValidationReport;
import org.gcube.application.geoportal.model.report.ValidationReport.ValidationStatus;
import org.gcube.application.geoportal.utils.Files;
import org.gcube.application.geoportal.utils.Serialization;
import org.junit.Assert;

import com.fasterxml.jackson.core.JsonProcessingException;

public class UseCases {

	public static void main(String[] args) throws FileNotFoundException, IOException {
		TokenSetter.set("/gcube/devsec/devVRE");
		
//		TokenSetter.set("/pred4s/preprod/preVRE");

		try {		
			
			
			//CREATE NEW
			int numConcessioni=1;
			Concessione registered=null;
			System.out.println("Try to create.. "+numConcessioni);
			for(int i=0;i<numConcessioni;i++)
				registered=registerNewConcessione();
			
			
			
			
		    long id=registered.getId();
//			long id=22;
		    Concessione loaded=readConcessione(id);
		    System.out.println("LAST LOADED : "+loaded);
//		    
//		    ManagerFactory.getByRecord(loaded).publish();
//		    System.out.println("DONE");
		    
		    
			//READ BY ID 
//			long id=72;
//			System.out.println("Tryint to read by id ");
//			System.out.println("Fra [67]"+readConcessione(67).getImmaginiRappresentative());
//			System.out.println("Test [72]"+readConcessione(72).getImmaginiRappresentative());
//			System.out.println("Test [1]"+readConcessione(1).getImmaginiRappresentative());
//		    
			
			
//			//GET LIST
//			System.out.println(getList());
			
			//GET LIST BY TYPE
//			System.out.println(getConcessioneList());
			
			
		    
		    
		    
		}catch(Throwable t) {
			System.err.println("ALERT "+t.getMessage());
			t.printStackTrace(System.err);
			throw new RuntimeException(t);
		}finally {
			System.out.println("Shutting down..");
			AbstractRecordManager.shutdown();
		}
		
		
	}


	public static Concessione registerNewConcessione() throws FileNotFoundException, IOException, PersistenceException, ValidationException, PublishException{
		ConcessioneManager manager=null;
			//Preparo l'istanza del modello con i vari campi compilati e senza gli allegati
			Concessione conc=TestModel.prepareEmptyConcessione();

			//Ottengo il manager per il progetto da registrare (tipi progetto : concessioni, mosi, mopr etc..)
			manager=ManagerFactory.registerNew(conc);

			//Preparo l'istanza dell'oggetto relazione scavo con i campi compilati e senza allegati
			RelazioneScavo rel=TestModel.prepareConcessione().getRelazioneScavo();

			//Istruisco il manager per gestire il payload della relazione di scavo, specificando il nome del file originale
			manager.setRelazioneScavo(rel, 
					new InputStreamDescriptor(
							new FileInputStream(Files.getFileFromResources("concessioni/relazione.pdf")),"relazione.pdf"));

			//Per ogni immagine preparo l'istanza dell'oggetto uploadedimage con i campi compilati e senza allegati
			for(UploadedImage img:TestModel.prepareConcessione().getImmaginiRappresentative())
				//Istruisco il manager per gestire il payload dell' immagine, specificando il nome del file originale
				manager.addImmagineRappresentativa(img, 
						new InputStreamDescriptor(new FileInputStream(Files.getFileFromResources("concessioni/immagine.png")),img.getTitolo()));

			//Per ogni immagine preparo l'istanza dell'oggetto layerconcessione con i campi compilati e senza allegati
			LayerConcessione posizionamento=TestModel.prepareConcessione().getPosizionamentoScavo();
			//Istruisco il manager per gestire il/i payload del layer, specificando i nomi dei file originali
			manager.setPosizionamento(posizionamento, 
					new InputStreamDescriptor(new FileInputStream(Files.getFileFromResources("concessioni/pos.dbf")),"pos.dbf"),
					new InputStreamDescriptor(new FileInputStream(Files.getFileFromResources("concessioni/pos.prj")),"pos.prj"),
					new InputStreamDescriptor(new FileInputStream(Files.getFileFromResources("concessioni/pos.qpj")),"pos.qpj"),
					new InputStreamDescriptor(new FileInputStream(Files.getFileFromResources("concessioni/pos.shp")),"pos.shp"),
					new InputStreamDescriptor(new FileInputStream(Files.getFileFromResources("concessioni/pos.shx")),"pos.shx"));

			for(LayerConcessione layer:TestModel.prepareConcessione().getPianteFineScavo())
				//Istruisco il manager per gestire il/i payload del layer, specificando i nomi dei file originali
				manager.addPiantaFineScavo(layer, 
						new InputStreamDescriptor(new FileInputStream(Files.getFileFromResources("concessioni/pos.dbf")),"qualche Pianta.dbf"),
						new InputStreamDescriptor(new FileInputStream(Files.getFileFromResources("concessioni/pos.prj")),"qualche Pianta.prj"),
						new InputStreamDescriptor(new FileInputStream(Files.getFileFromResources("concessioni/pos.qpj")),"qualche Pianta.qpj"),
						new InputStreamDescriptor(new FileInputStream(Files.getFileFromResources("concessioni/pos.shp")),"qualche Pianta.shp"),
						new InputStreamDescriptor(new FileInputStream(Files.getFileFromResources("concessioni/pos.shx")),"qualche Pianta.shx"));


			//If true -> data are published into the SDI 
			Boolean publish=true;

			//NB la validazione viene CMQ triggerata a commit time. 
			//In caso di errore viene lanciata una ValidationException 
			Concessione prepared=manager.getRecord();
			System.out.println("Object before validation is "+prepared);
			ValidationReport report=manager.getRecord().validate();
			System.out.println("Report is : "+report.prettyPrint());
			Assert.assertEquals(report.getStatus(),ValidationStatus.PASSED);
			System.out.println("Object after validation is "+prepared);
			
			
			/*Chiedo al manager di salvare il progetto, causando :
			 *scrittura sul WS
			 *pubblicazione sull'SDI (boolean publish)
			 *scrittura sul DB di applicazione sia dei meta che dei vari link */
			
			//Metodo con eccezioni
			Concessione registered=manager.commit(publish);


			//Metodo con report
//			PublicationReport pubReport=manager.commitSafely(publish);
//			Concessione registered=(Concessione) pubReport.getTheRecord();
//			
//			System.out.println("REGISTERED "+registered);
//
//			System.out.println("Report is "+pubReport.prettyPrint());
//			Assert.assertFalse(pubReport.getStatus().equals(ValidationStatus.ERROR));
			
			manager.close();
			return registered;
			//--- FINALLY --/
		
	}

	
	public static Concessione readConcessione(long id) {
		ConcessioneManager manager=null;
		try {
			manager=ManagerFactory.getByRecordID(id);
			System.out.println(manager.getRecord());
		return manager.getRecord();
		}finally {
			if(manager!=null)
				manager.close();
		}
	}
	
	
	public static String getList(){
		StringBuilder builder=new StringBuilder();
		for(Record r : ManagerFactory.getList()) {
			builder.append("Record ["+r.getId()+"\t\""+r.getNome()+"\t"+r.getRecordType()+"]");
		}
		return builder.toString();
	}
	
	
	public static String getConcessioneList() throws JsonProcessingException{
		StringBuilder builder=new StringBuilder();
		for(Concessione r : ManagerFactory.getList(Concessione.class)) {
			try{
				Serialization.asJSON(r);
			}catch(Throwable t) {
				System.err.println(t);
			}
			builder.append("Concessione ["+r.getId()+"\t\""+r.getNome()+"\"\t"+r.getRecordType()+"\t : "+r.validate().getStatus()+"]");
		}
		return builder.toString();
	}
}
