/*
 * Copyright 2017 Crown Copyright
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package stroom.task.impl;

import stroom.event.logging.rs.api.AutoLogged;
import stroom.event.logging.rs.api.AutoLogged.OperationType;
import stroom.node.api.NodeService;
import stroom.task.shared.FindTaskProgressCriteria;
import stroom.task.shared.FindTaskProgressRequest;
import stroom.task.shared.TaskProgress;
import stroom.task.shared.TaskProgressResponse;
import stroom.task.shared.TaskResource;
import stroom.task.shared.TerminateTaskProgressRequest;
import stroom.util.logging.LambdaLogger;
import stroom.util.logging.LambdaLoggerFactory;
import stroom.util.servlet.SessionIdProvider;
import stroom.util.shared.ResourcePaths;
import stroom.util.shared.ResultPage;

import event.logging.EventAction;
import event.logging.ProcessAction;
import event.logging.ProcessEventAction;

import javax.inject.Inject;
import javax.inject.Provider;
import javax.ws.rs.client.Entity;

//@AutoLogged  see
class TaskResourceImpl implements TaskResource {

    private static final LambdaLogger LOGGER = LambdaLoggerFactory.getLogger(TaskResourceImpl.class);

    private final Provider<TaskManagerImpl> taskManagerProvider;
    private final Provider<SessionIdProvider> sessionIdProvider;
    private final Provider<NodeService> nodeServiceProvider;

    @Inject
    TaskResourceImpl(final Provider<TaskManagerImpl> taskManagerProvider,
                     final Provider<SessionIdProvider> sessionIdProvider,
                     final Provider<NodeService> nodeServiceProvider) {
        this.taskManagerProvider = taskManagerProvider;
        this.sessionIdProvider = sessionIdProvider;
        this.nodeServiceProvider = nodeServiceProvider;
    }

    @Override
    public TaskProgressResponse list(final String nodeName) {
        return find(nodeName, new FindTaskProgressRequest(new FindTaskProgressCriteria()));
    }

    @Override
    public TaskProgressResponse find(final String nodeName, final FindTaskProgressRequest request) {
        return nodeServiceProvider.get()
                .remoteRestResult(
                        nodeName,
                        TaskProgressResponse.class,
                        () -> ResourcePaths.buildAuthenticatedApiPath(
                                TaskResource.BASE_PATH,
                                TaskResource.FIND_PATH_PART,
                                nodeName),
                        () -> {
                            final ResultPage<TaskProgress> resultPage = taskManagerProvider.get()
                                    .find(request.getCriteria());
                            return new TaskProgressResponse(
                                    resultPage.getValues(),
                                    resultPage.getPageResponse());
                        },
                        builder ->
                                builder.post(Entity.json(request)));
    }

    @Override
    public TaskProgressResponse userTasks(final String nodeName) {
        try {
            final String sessionId = sessionIdProvider.get().get();
            if (sessionId != null) {
                final FindTaskProgressCriteria criteria = new FindTaskProgressCriteria();
                criteria.setSort(FindTaskProgressCriteria.FIELD_AGE, true, false);
                criteria.setSessionId(sessionId);
                final FindTaskProgressRequest findTaskProgressRequest = new FindTaskProgressRequest(criteria);
                return find(nodeName, findTaskProgressRequest);
            }
        } catch (final RuntimeException e) {
            LOGGER.error(e::getMessage, e);
            throw e;
        }
        return null;
    }

    @Override
    @AutoLogged(
            value = OperationType.PROCESS,
            verb = "Terminating")
    public Boolean terminate(final String nodeName, final TerminateTaskProgressRequest request) {

        // TODO @AT Add custom logging to set the Process.Action to TERMINATE
//        Runnable work = () -> {
        nodeServiceProvider.get()
                .remoteRestCall(
                        nodeName,
                        () -> ResourcePaths.buildAuthenticatedApiPath(
                                TaskResource.BASE_PATH,
                                TaskResource.TERMINATE_PATH_PART,
                                nodeName),
                        () ->
                                taskManagerProvider.get().terminate(
                                        request.getCriteria(),
                                        request.isKill()),
                        builder ->
                                builder.post(Entity.json(request)));
//        };

//        stroomEventLoggingService.loggedAction(
//                StroomEventLoggingUtil.buildTypeId(this, "terminate"),
//                "just kill it",
//                ProcessEventAction.builder()
//                        .withAction(ProcessAction.TERMINATE)
//                        .withInput(stroomEventLoggingService.convertToMulti(request))
//                        .build(),
//                () -> {
//                    // do stuff
//                });

        return true;
    }

    static interface EventActionDecorator<T extends EventAction> {

        T decorate(final T eventAction);
    }

    static class TerminateDecorator implements EventActionDecorator<ProcessEventAction> {

        @Override
        public ProcessEventAction decorate(final ProcessEventAction eventAction) {
            return eventAction.newCopyBuilder()
                    .withAction(ProcessAction.TERMINATE)
                    .build();
        }
    }
}

@@ -620,16 +620,70 @@
 .impl;%0A%0A
+import stroom.event.logging.api.EventActionDecorator;%0A
 import s
@@ -1525,18 +1525,16 @@
 ntity;%0A%0A
-//
 @AutoLog
@@ -1540,13 +1540,8 @@
 gged
-  see
 %0Acla
@@ -3496,32 +3496,70 @@
 %0A%0A    @Override%0A
+    @AutoLogged(OperationType.SEARCH)%0A
     public TaskP
@@ -4318,29 +4318,16 @@
 oLogged(
-%0A            
 value = 
@@ -4348,16 +4348,38 @@
 PROCESS,
+ verb = %22Terminating%22,
 %0A       
@@ -4383,32 +4383,36 @@
         
-verb
+decorator
  = 
-%22
 Terminat
 ing%22)%0A  
@@ -4403,20 +4403,32 @@
 Terminat
-ing%22
+eDecorator.class
 )%0A    pu
@@ -4522,121 +4522,8 @@
 t) %7B
-%0A%0A        // TODO @AT Add custom logging to set the Process.Action to TERMINATE%0A//        Runnable work = () -%3E %7B
 %0A   
@@ -5185,631 +5185,28 @@
 ));%0A
-//        %7D;%0A%0A//        stroomEventLoggingService.loggedAction(%0A//                StroomEventLoggingUtil.buildTypeId(this, %22terminate%22),%0A//                %22just kill it%22,%0A//                ProcessEventAction.builder()%0A//                        .withAction(ProcessAction.TERMINATE)%0A//                        .withInput(stroomEventLoggingService.convertToMulti(request))%0A//                        .build(),%0A//                () -%3E %7B%0A//                    // do stuff%0A//                %7D);%0A%0A        return true;%0A    %7D%0A%0A    static interface EventActionDecorator%3CT extends EventAction%3E %7B%0A%0A        T decorate(final T eventAction)
+%0A        return true
 ;%0A  

Apply REST standards to TaskResourceImpl