package io.cattle.platform.process.common.handler;

import io.cattle.platform.engine.handler.HandlerResult;
import io.cattle.platform.engine.process.ProcessInstance;
import io.cattle.platform.engine.process.ProcessState;
import io.cattle.platform.eventing.EventCallOptions;
import io.cattle.platform.eventing.EventService;
import io.cattle.platform.eventing.model.Event;
import io.cattle.platform.eventing.model.EventVO;
import io.cattle.platform.object.ObjectManager;
import io.cattle.platform.object.meta.ObjectMetaDataManager;
import io.cattle.platform.object.process.ObjectProcessManager;
import io.cattle.platform.object.util.ObjectUtils;
import io.cattle.platform.util.type.CollectionUtils;
import io.cattle.platform.util.type.NamedUtils;
import io.cattle.platform.util.type.Priority;

import java.util.Map;

import javax.inject.Inject;

public class EventBasedProcessHandler extends AbstractObjectProcessHandler implements Priority {

    public static String DEFAULT_NAME = "EventBased";

    EventService eventService;
    String[] processNames;
    String eventName;
    Integer retry;
    Long timeoutMillis;
    int priority = Priority.SPECIFIC;

    public EventBasedProcessHandler(EventService eventService, ObjectManager objectManager, ObjectProcessManager objectProcessManager,
            ObjectMetaDataManager objectMetaDataManager) {
        this();
        this.eventService = eventService;
        this.objectManager = objectManager;
        this.objectProcessManager = objectProcessManager;
        this.objectMetaDataManager = objectMetaDataManager;
    }

    public EventBasedProcessHandler() {
        if (this.getClass() == EventBasedProcessHandler.class) {
            setName(DEFAULT_NAME);
        }
    }

    @Override
    public String[] getProcessNames() {
        if (DEFAULT_NAME.equals(getName())) {
            return new String[0];
        }
        if (processNames == null) {
            return new String[] { NamedUtils.toDotSeparated(getName()) };
        }
        return processNames;
    }

    @Override
    public HandlerResult handle(ProcessState state, ProcessInstance process) {
        Object resource = state.getResource();
        String type = objectManager.getType(resource);
        if (type == null) {
            type = resource.getClass().getName();
        }

        String idString = null;
        Object id = ObjectUtils.getId(resource);

        if (id != null) {
            idString = id.toString();
        }

        String eventName = getEventName() == null ? process.getName() : getEventName();

        Event request = EventVO.newEvent(eventName).withResourceId(idString).withResourceType(type).withData(state.getData());

        Event response = eventService.callSync(request, new EventCallOptions(retry, timeoutMillis));

        return postEvent(state, process, CollectionUtils.toMap(response.getData()));
    }

    protected HandlerResult postEvent(ProcessState state, ProcessInstance process, Map<Object, Object> data) {
        return new HandlerResult(data);
    }

    public EventService getEventService() {
        return eventService;
    }

    @Inject
    public void setEventService(EventService eventService) {
        this.eventService = eventService;
    }

    @Override
    public ObjectManager getObjectManager() {
        return objectManager;
    }

    @Override
    @Inject
    public void setObjectManager(ObjectManager objectManager) {
        this.objectManager = objectManager;
    }

    public void setProcessNames(String[] processNames) {
        this.processNames = processNames;
    }

    public String getEventName() {
        return eventName;
    }

    public void setEventName(String eventName) {
        this.eventName = eventName;
    }

    public Integer getRetry() {
        return retry;
    }

    public void setRetry(Integer retry) {
        this.retry = retry;
    }

    public Long getTimeoutMillis() {
        return timeoutMillis;
    }

    public void setTimeoutMillis(Long timeoutMillis) {
        this.timeoutMillis = timeoutMillis;
    }

    @Override
    public int getPriority() {
        return priority;
    }

    public void setPriority(int priority) {
        this.priority = priority;
    }

}
@@ -267,16 +267,66 @@
 ptions;%0A
+import io.cattle.platform.eventing.EventProgress;%0A
 import i
@@ -362,24 +362,24 @@
 entService;%0A
-
 import io.ca
@@ -835,16 +835,42 @@
 ority;%0A%0A
+import java.util.HashMap;%0A
 import j
@@ -2203,24 +2203,30 @@
 ) %7B%0A        
+final 
 Object resou
@@ -2787,93 +2787,1044 @@
 vent
- response = eventService.callSync(request, new EventCallOptions(retry, timeoutMillis)
+CallOptions options = new EventCallOptions(retry, timeoutMillis);%0A        options.setProgressIsKeepAlive(true);%0A        options.setProgress(new EventProgress() %7B%0A            @Override%0A            public void progress(Event event) %7B%0A                Map%3CString, Object%3E data = new HashMap%3CString, Object%3E();%0A                String transitioning = event.getTransitioningMessage();%0A                Integer progress = event.getTransitioningProgress();%0A%0A                if (transitioning != null) %7B%0A                    data.put(ObjectMetaDataManager.TRANSITIONING_MESSAGE_FIELD, transitioning);%0A                %7D%0A%0A                if (progress != null) %7B%0A                    data.put(ObjectMetaDataManager.TRANSITIONING_PROGRESS_FIELD, progress);%0A                %7D%0A%0A                if (data.size() %3E 0) %7B%0A                    Object reloaded = objectManager.reload(resource);%0A                    objectManager.setFields(reloaded, data);%0A                %7D%0A            %7D%0A        %7D);%0A        Event response = eventService.callSync(request, options
 );%0A%0A

Allow event based process handler to set transition messages