package org.gcube.application.geoportal.service.engine.mongo;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mongodb.Block;
import com.mongodb.DBObject;
import com.mongodb.client.AggregateIterable;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.FindOneAndReplaceOptions;
import com.mongodb.client.model.FindOneAndUpdateOptions;
import com.mongodb.client.model.ReturnDocument;
import com.mongodb.util.JSON;

import org.bson.BSON;
import org.bson.Document;
import org.bson.types.ObjectId;
import org.gcube.application.cms.implementations.ImplementationProvider;
import org.gcube.application.cms.serialization.Serialization;
import org.gcube.application.cms.tests.TokenSetter;
import org.gcube.application.geoportal.common.model.document.Lock;
import org.gcube.application.geoportal.common.model.document.Project;
import org.gcube.application.geoportal.common.model.document.lifecycle.LifecycleInformation;
import org.gcube.application.geoportal.common.model.rest.ConfigurationException;
import org.gcube.application.geoportal.common.model.useCaseDescriptor.UseCaseDescriptor;
import org.gcube.application.geoportal.common.utils.tests.GCubeTest;
import org.gcube.application.geoportal.service.engine.providers.MongoClientProvider;
import org.gcube.application.geoportal.service.model.internal.db.Mongo;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Consumer;

public class ProjectsManualUpdate {
	
	private static String testContext = "/gcube/devsec/devVRE";

    public static void main(String[] args) throws ConfigurationException {
        ImplementationProvider.get().setEngine(new MongoClientProvider() {
            @Override
            public Mongo getObject() throws ConfigurationException {
                TokenSetter.set(testContext);
                return super.getObject();
            }
        },Mongo.class);

        MongoTester mongo = new MongoTester("profiledConcessioni");

            // UPDATE PHASE = DRAFT
//        mongo.getCollection().find().forEach((Consumer) t ->{
//            Project p= Serialization.convert(t, Project.class);
//            p.getLifecycleInformation().setPhase(LifecycleInformation.CommonPhases.DRAFT_PHASE);
//            try{
//                mongo.replaceDoc(Serialization.asDocumentWithId(p),new ObjectId(p.getId()));
//            }catch(Throwable e){throw new RuntimeException(e);}
//        });

        
        String projectId = "6425598a8593b215a1281e1c";
        
        Document doc = mongo.getDocById(new ObjectId(projectId));
        System.out.println(doc.toJson());
        Project theSourceProject = Serialization.convert(doc, Project.class);
        
        Document theSourceDocument = theSourceProject.getTheDocument();
        System.out.println("theSourceDocument:" +theSourceDocument.toJson());
       
//        Document updatedDocument =  new Document(theSourceDocument);
//        updatedDocument.put("nome", "Nome aggiornato");

		
		/*List<Document> listDocument = new ArrayList<Document>();
		//listDocument.add(theSourceDocument);
		listDocument.add(updatedDocument);
		
		Document match = new Document();
		match.put("$match", new Document(Project.ID, theSourceProject.getId()));
		
		Document merge = new Document();
		merge.put("$mergeObjects", listDocument);
		
		Document project = new Document();
		project.put("$project", new Document(Project.THE_DOCUMENT, merge));
		
		
		List<Document> query = new ArrayList<Document>();
		query.add(match);
		query.add(project);


		System.out.println("Query: "+query);*/
       //pipeline.append(new Document().append("$match",match));
		
		Document filter = new Document(Project.ID, new ObjectId(theSourceProject.getId()));
		
		Document updatedProject = new Document();
		Document update = new Document();
		update.append("nome", "nome aggiornato");
		Document subDocument = new Document();
		subDocument.append("abstractIta","abstract cambiato");
		update.append("abstractRelazione", subDocument);
		updatedProject.put(Project.THE_DOCUMENT, update);
		
		System.out.println("updated: "+update.toJson());
		
		theSourceDocument.putAll(update);
		
//		DBObject obj1 = (DBObject) JSON.parse(theSourceDocument.toJson());
//		DBObject obj2 = (DBObject) JSON.parse(update.toJson());
//		obj1.putAll(obj2);
//		System.out.println("obj1: "+obj1.toString());
		
//		theSourceDocument.forEach(null);
//		
//		Object object = theSourceDocument.merge(Project.THE_DOCUMENT,updatedProject,(val1,val2) -> val2);
		
		//System.out.println("object: "+theSourceDocument.toJson());
		
		
        ObjectMapper mapper = new ObjectMapper();
        JsonNode node1;
		try {
			
			node1 = mapper.readTree(theSourceDocument.toJson());
	
			JsonNode node2 = mapper.readerForUpdating(node1)
                .readTree(update.toJson());
        
        System.out.println("node2: "+node2.toString());
        
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        
//		System.out.println("updatedProjectDocument: "+updatedProject.toJson());
//		
//		Document setOperation = new Document();
//		setOperation.append("$set", updatedProject);
//		
////		Object newProject = mongo.getCollection().findOneAndUpdate(
////				filter, 
////				setOperation, 
////				new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER));
//		
//		Object newProject = mongo.getCollection().updateOne(
//				filter, 
//				setOperation);
//        
//        Project theNewProject = Serialization.convert(newProject, Project.class);
//
//        
//        System.out.println("theNewProject: "+theNewProject.toString());

        //mongo.getCollection().deleteMany(Filters.eq("_theDocument",null));
    }

}
