package org.gcube.application.cms.plugins.implementations.executions;

import lombok.Getter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.gcube.application.cms.plugins.faults.InsufficientPrivileges;
import org.gcube.application.cms.plugins.faults.StepException;
import org.gcube.application.cms.plugins.reports.DocumentHandlingReport;
import org.gcube.application.cms.plugins.requests.BaseExecutionRequest;
import org.gcube.application.geoportal.common.model.plugins.OperationDescriptor;
import org.gcube.application.geoportal.common.model.rest.ConfigurationException;
import org.gcube.application.geoportal.common.model.useCaseDescriptor.HandlerDeclaration;


@Slf4j
@RequiredArgsConstructor
public abstract class GuardedExecution<R extends BaseExecutionRequest,T extends DocumentHandlingReport> {

    @Getter
    protected T result = null;


    @NonNull
    @Getter
    private OperationDescriptor op;


    protected T theReport;

    protected void checks() throws ConfigurationException, InsufficientPrivileges {
        if(theReport.getTheRequest()==null) throw new RuntimeException("Unexpected state : request cannot be null");

        // Check document phase
        if(op.getAppliableToPhases()!=null&&!op.getAppliableToPhases().isEmpty()) {
            String currentPhase = theReport.getTheRequest().getDocument().getLifecycleInformation().getPhase();
            if(!op.getAppliableToPhases().contains(currentPhase))
                new StepException("Document must be in one of the following phases : "+ op.getAppliableToPhases());
        }
    }


    public T execute() throws Exception {
        log.trace("Executing {} ",theReport.getTheRequest());

        checks();

        result = run();
        log.trace("Report is {} ",theReport);
        return result;
    }

    public T getResult() {
        return result;
    }
    protected abstract T run() throws Exception;

    public GuardedExecution<R, T> setTheReport(T theReport) {
        this.theReport = theReport;
        return this;
    }

    protected HandlerDeclaration config=null;

    public void setHandlerConfiguration(HandlerDeclaration config){
        this.config=config;
    }
}
