package org.gcube.application.cms.tests.model;

import com.vdurmont.semver4j.Semver;
import org.bson.Document;
import org.gcube.application.geoportal.common.model.document.Project;
import org.gcube.application.geoportal.common.model.document.access.Access;
import org.gcube.application.geoportal.common.model.document.access.AccessPolicy;
import org.gcube.application.geoportal.common.model.document.accounting.AccountingInfo;
import org.gcube.application.geoportal.common.model.document.accounting.Context;
import org.gcube.application.geoportal.common.model.document.accounting.PublicationInfo;
import org.gcube.application.geoportal.common.model.document.accounting.User;
import org.gcube.application.geoportal.common.model.document.lifecycle.LifecycleInformation;
import org.gcube.application.geoportal.common.model.plugins.LifecycleManagerDescriptor;
import org.gcube.application.geoportal.common.model.useCaseDescriptor.DataAccessPolicy;
import org.gcube.application.geoportal.common.model.useCaseDescriptor.HandlerDeclaration;
import org.gcube.application.geoportal.common.model.useCaseDescriptor.UseCaseDescriptor;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.UUID;

import static junit.framework.TestCase.assertTrue;

public class BasicTests {

    protected User getCurrentUser(){
        User u= new User();
        u.setUsername("fake-user");
        return u;
    }

    protected UseCaseDescriptor getUCD(){
        return initUCD(getContext(),getCurrentUser());
    }

    protected Document getBasicDocument(){
        return new Document();
    }

    protected Project getBasicProject(){
        return initProject(getBasicDocument(),getUCD(), getCurrentUser(), getContext());
    }

    protected Context getContext(){
        Context toReturn = new Context();
        toReturn.setName("My Fake Vre");
        toReturn.setId("FAKE-VRE");
        return toReturn;
    }

    protected PublicationInfo getCurrentInfo(){
        return initPublicationInfo(getUCD(),getContext(),getCurrentUser());
    }

    protected static PublicationInfo initPublicationInfo(UseCaseDescriptor ucd, Context ctx, User user){
        PublicationInfo toReturn = new PublicationInfo();

        // TODO Set Access From UseCaseDescriptor
        Access access=new Access();
        access.setLicense("");
        access.setPolicy(AccessPolicy.OPEN);
        toReturn.setAccess(access);

        toReturn.setCreationInfo(initAccountingInfo(ctx,user));
        return toReturn;
    }

    protected static AccountingInfo initAccountingInfo(Context ctx, User user){
        AccountingInfo accInfo = new AccountingInfo();
        accInfo.setInstant(LocalDateTime.now());
        accInfo.setContext(ctx);
        accInfo.setUser(user);
        return accInfo;
    }

    protected static Project initProject(Document doc, UseCaseDescriptor ucd,User user, Context ctx){
        Project p = new Project();

        p.setId(UUID.randomUUID().toString());
        p.setInfo(initPublicationInfo(ucd,ctx,user));

        p.setProfileID(ucd.getId());
        p.setProfileVersion(ucd.getVersion());
        p.setVersion(new Semver("1.0.0"));

        LifecycleInformation draftInfo=new LifecycleInformation().cleanState();
        draftInfo.setPhase(LifecycleInformation.CommonPhases.DRAFT_PHASE);
        draftInfo.setLastOperationStatus(LifecycleInformation.Status.OK);
        p.setLifecycleInformation(draftInfo);
        return p;
    }

    protected static UseCaseDescriptor initUCD(Context ctx, User u){
        UseCaseDescriptor ucd = new UseCaseDescriptor();
        ucd.setName("Test UCD");
        ucd.setId("test-ucd");
        ucd.setDescription("Just a test dummy profile");
        ucd.setCreationInfo(initAccountingInfo(ctx,u));

        ucd.setVersion(new Semver("1.0.0"));
        HandlerDeclaration h= new HandlerDeclaration();
        h.setType(LifecycleManagerDescriptor.LIFECYCLE_MANAGER_TYPE);
        h.setId(UUID.randomUUID().toString());
        ucd.setHandlers(Collections.singletonList(h));

        DataAccessPolicy p =new DataAccessPolicy();
        p.setPolicy(new DataAccessPolicy.Policy());
        p.getPolicy().setRead(DataAccessPolicy.Policy.Type.any);
        p.getPolicy().setWrite(DataAccessPolicy.Policy.Type.any);
        ucd.setDataAccessPolicies(Collections.singletonList(p));
        return ucd;
    }



    public static void validate (Project doc){
        assertTrue(doc!=null);
        assertTrue(doc.getId()!=null);
        assertTrue(doc.getLifecycleInformation().getPhase()!=null);
        assertTrue(doc.getLifecycleInformation().getLastOperationStatus()!=null);
        if(doc.getLifecycleInformation().getLastOperationStatus().equals(LifecycleInformation.Status.ERROR))
            assertTrue(doc.getLifecycleInformation().getErrorMessages().size()>0);
        if(doc.getLifecycleInformation().getLastOperationStatus().equals(LifecycleInformation.Status.WARNING))
            assertTrue(doc.getLifecycleInformation().getWarningMessages().size()>0);

        if(doc.getLifecycleInformation().getTriggeredEvents()!=null)
            doc.getLifecycleInformation().getTriggeredEvents().forEach(triggeredEvents -> {
                assertTrue(triggeredEvents.getEvent()!=null);
                assertTrue(triggeredEvents.getLastOperationStatus()!=null);
                if(triggeredEvents.getLastOperationStatus().equals(LifecycleInformation.Status.ERROR))
                    assertTrue(triggeredEvents.getErrorMessages().size()>0);
                if(triggeredEvents.getLastOperationStatus().equals(LifecycleInformation.Status.WARNING))
                    assertTrue(triggeredEvents.getWarningMessages().size()>0);
            });


        assertTrue(doc.getInfo()!=null);
        assertTrue(doc.getInfo().getCreationInfo()!=null);
        assertTrue(doc.getInfo().getCreationInfo().getContext()!=null);
        assertTrue(doc.getInfo().getCreationInfo().getContext().getId()!=null);
        assertTrue(doc.getInfo().getCreationInfo().getContext().getName()!=null);
        assertTrue(doc.getInfo().getCreationInfo().getInstant()!=null);
        assertTrue(doc.getInfo().getCreationInfo().getInstant()!=null);
        assertTrue(doc.getInfo().getCreationInfo().getUser()!=null);
        assertTrue(doc.getInfo().getCreationInfo().getUser().getUsername()!=null);

        assertTrue(doc.getTheDocument()!=null);
    }
}
