package org.gcube.application.geoportal.clients;

import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.extern.slf4j.Slf4j;
import org.bson.Document;
import org.gcube.application.geoportal.common.model.configuration.Configuration;
import org.gcube.application.geoportal.common.model.document.Project;
import org.gcube.application.geoportal.common.model.document.relationships.RelationshipNavigationObject;
import org.gcube.application.geoportal.common.model.rest.CreateRelationshipRequest;
import org.gcube.application.geoportal.common.model.rest.DeleteRelationshipRequest;
import org.gcube.application.geoportal.common.model.rest.QueryRequest;
import org.gcube.application.geoportal.common.rest.Projects;
import org.gcube.application.geoportal.common.utils.tests.GCubeTest;
import org.junit.Test;

import java.rmi.RemoteException;
import java.time.LocalDateTime;
import java.util.Iterator;
import java.util.concurrent.atomic.AtomicLong;

import static org.gcube.application.geoportal.client.utils.Serialization.write;
import static org.junit.Assume.assumeTrue;

@Slf4j
public class ProfiledDocumentsTest<M extends Project,C extends Projects<M>> extends GenericUseCases {

//    protected String getProfileID(){return "basic";}

//    protected C getClient(){
//        return (C) customModel(getProfileID(), Project.class, DefaultDocumentsClient.class).build();
//    }


    @Test
    public void registerNew() throws RemoteException, JsonProcessingException {
        assumeTrue(GCubeTest.isTestInfrastructureEnabled());
        Projects<M> client = (Projects<M>) getClient();

        Document theDoc= Document.parse("{\n" +
                "\"posizionamentoScavo\" :{\n" +
                "\t\"titolo\" : \"mio titolo\"}}");

        theDoc.put("startTime", LocalDateTime.now());

        Project p =client.createNew(theDoc);

        log.debug("Registered project (AS JSON) : {}", write(p));
    }

    @Test
    public void getConfiguration() throws Exception {
        assumeTrue(GCubeTest.isTestInfrastructureEnabled());
        Projects<M> client = (Projects<M>) getClient();
        Configuration config=client.getConfiguration();
        System.out.println("Configuration is "+ config);
    }


    @Test
    public void list() throws Exception {
        assumeTrue(GCubeTest.isTestInfrastructureEnabled());
        Projects<M> client = (Projects<M>) getClient();
        AtomicLong counter=new AtomicLong(0);
        client.query(new QueryRequest()).forEachRemaining( M -> counter.incrementAndGet());
        System.out.println("Found "+counter.get()+" elements");
        System.out.println("Getting JSON ");
        System.out.println(client.queryForJSON(new QueryRequest()));
    }

    @Test
    public void scanStatusByID() throws Exception {
        assumeTrue(GCubeTest.isTestInfrastructureEnabled());
        Projects<M> client = (Projects<M>) getClient();
        AtomicLong counter=new AtomicLong(0);
        client.query(new QueryRequest()).forEachRemaining( m -> {
            System.out.print(counter.incrementAndGet()+ ", ID : "+m.getId());
            try {
                M proj=client.getById(m.getId());
                System.out.println("... OK.. STATUS : "+proj.getLifecycleInformation());
            } catch (RemoteException e) {
                System.err.println(" Error with "+m.getId());
                System.err.println(e);
                System.out.println("... ERRR !!!!");
            }
        });
    }

    @Test
    public void testRelationships() throws Exception{
        assumeTrue(GCubeTest.isTestInfrastructureEnabled());
        Projects<M> client = (Projects<M>) getClient();
        Project source = client.createNew(new Document().append("field","value"));
        Project target = client.createNew(new Document().append("field2","value"));

        String relId="associate";


        Project linkedSource = client.setRelation(
                new CreateRelationshipRequest(source.getId(),relId,
                        target.getId(), null));

        assumeTrue(linkedSource.getRelationships()!=null);
        assumeTrue(!linkedSource.getRelationships().isEmpty());
        assumeTrue(linkedSource.getRelationships().get(0).getRelationshipName().equals(relId));
        assumeTrue(linkedSource.getRelationships().get(0).getTargetID().equals(target.getId()));
        assumeTrue(linkedSource.getRelationships().get(0).getTargetUCD().equals(target.getProfileID()));

        Iterator<RelationshipNavigationObject> it = client.getRelationshipChain(source.getId(),relId,true);
        System.out.println("Scanning rel ..");
        it.forEachRemaining(r -> {
            System.out.println(r.getTarget().getId());
            System.out.println("Children size : "+r.getChildren().size());
        });


        Project unLinkedSource = client.deleteRelation(
                new DeleteRelationshipRequest(source.getId(),relId,
                        target.getId(),null));


        assumeTrue(unLinkedSource.getRelationships()==null || unLinkedSource.getRelationships().isEmpty());

    }

}
