package org.gcube.application.geoportal.service.rest;

import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
import lombok.extern.slf4j.Slf4j;
import org.gcube.application.cms.implementations.ImplementationProvider;
import org.gcube.application.cms.serialization.Serialization;
import org.gcube.application.geoportal.common.model.useCaseDescriptor.UseCaseDescriptor;
import org.gcube.application.geoportal.common.rest.InterfaceConstants;
import org.gcube.application.geoportal.service.engine.mongo.UCDManagerI;

import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

@Path(InterfaceConstants.Methods.UCD)
@Slf4j
@RequestHeaders({
        @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
        @RequestHeader( name = "Content-Type", description = "application/json")
})
public class UseCaseDescriptors {


    private UCDManagerI getManager(){
        try{
            return ImplementationProvider.get().getProvidedObjectByClass(UCDManagerI.class);
        }catch(Throwable t){
            log.error("Unable to get UCD Engine",t);
            throw new WebApplicationException("Unable to access UC Engine", Response.Status.INTERNAL_SERVER_ERROR);
        }
    }




    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public UseCaseDescriptor createNew(UseCaseDescriptor toCreate) {
        return new GuardedMethod<UseCaseDescriptor>() {
            @Override
            protected UseCaseDescriptor run() throws Exception, WebApplicationException {
                log.info("Creating new UseCaseDescriptor ({})",toCreate);
                if(toCreate.getMongoId()!=null) throw new WebApplicationException("Cannot register Use Case Descriptor with mongo ID", Response.Status.BAD_REQUEST);
                if(toCreate.getId()==null) throw  new WebApplicationException("Missing mandatory field ID", Response.Status.BAD_REQUEST);
                UseCaseDescriptor toReturn = getManager().put(toCreate);
                if(toReturn == null){
                    log.warn("NB Cached backend implementation is slow beware of that");
                }
                log.info("Created new UseCaseDescriptor (ID {})",toReturn.getId());
                return toReturn;
            }
        }.execute().getResult();
    }

    @PUT
    @Path("{"+InterfaceConstants.Parameters.UCID +"}")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public UseCaseDescriptor update(@PathParam(InterfaceConstants.Parameters.UCID) String profileId, UseCaseDescriptor d) {
        return new GuardedMethod<UseCaseDescriptor>() {
            @Override
            protected UseCaseDescriptor run() throws Exception, WebApplicationException {
                log.warn("Updating UseCaseDescriptor ({})",profileId);
                d.setId(profileId);
                return getManager().put(d);
            }
        }.execute().getResult();
    }


    @DELETE
    @Produces(MediaType.APPLICATION_JSON)
    @Path("{"+InterfaceConstants.Parameters.UCID +"}")
    public Boolean delete(@PathParam(InterfaceConstants.Parameters.UCID) String id,
                          @DefaultValue("false")
                          @QueryParam(InterfaceConstants.Parameters.FORCE) Boolean force) {
        return new GuardedMethod<Boolean>() {
            @Override
            protected Boolean run() throws Exception, WebApplicationException {
                log.warn("Deleting UseCaseDescriptor (ID {}). Force is {}",id,force);
                getManager().deleteById(id,force);
                return true;
            }
        }.execute().getResult();
    }


    // BY ID
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("{"+InterfaceConstants.Parameters.UCID +"}")
    public UseCaseDescriptor getById(@PathParam(InterfaceConstants.Parameters.UCID) String id) {
        return new GuardedMethod<UseCaseDescriptor>() {
            @Override
            protected UseCaseDescriptor run() throws Exception, WebApplicationException {
                UseCaseDescriptor toReturn = getManager().getById(id);
                if(toReturn == null ) throw new WebApplicationException("No UCD Matching ID "+id, Response.Status.NOT_FOUND);
                else return toReturn;
            }
        }.execute().getResult();
    }

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    @Path("/"+InterfaceConstants.Methods.QUERY_PATH)
    public Iterable<?> query(String queryString){
        return new GuardedMethod<Iterable<?>>() {
            @Override
            protected Iterable<?> run() throws Exception, WebApplicationException {
                return getManager().query(Serialization.parseQuery(queryString));
            }
        }.execute().getResult();
    }

}
