/*
 * 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.processor.impl;

import stroom.entity.shared.ExpressionCriteria;
import stroom.event.logging.api.DocumentEventLog;
import stroom.event.logging.api.StroomEventLoggingUtil;
import stroom.node.api.NodeCallUtil;
import stroom.node.api.NodeInfo;
import stroom.node.api.NodeService;
import stroom.processor.api.ProcessorTaskService;
import stroom.processor.shared.AssignTasksRequest;
import stroom.processor.shared.ProcessorTask;
import stroom.processor.shared.ProcessorTaskList;
import stroom.processor.shared.ProcessorTaskResource;
import stroom.processor.shared.ProcessorTaskSummary;
import stroom.util.jersey.WebTargetFactory;
import stroom.util.shared.ResourcePaths;
import stroom.util.shared.ResultPage;

import event.logging.Query;

import javax.inject.Inject;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

class ProcessorTaskResourceImpl implements ProcessorTaskResource {
    private final ProcessorTaskService processorTaskService;
    private final DocumentEventLog documentEventLog;
    private final NodeService nodeService;
    private final NodeInfo nodeInfo;
    private final WebTargetFactory webTargetFactory;
    private final ProcessorTaskManager processorTaskManager;

    @Inject
    ProcessorTaskResourceImpl(final ProcessorTaskService processorTaskService,
                              final DocumentEventLog documentEventLog,
                              final NodeService nodeService,
                              final NodeInfo nodeInfo,
                              final WebTargetFactory webTargetFactory,
                              final ProcessorTaskManager processorTaskManager) {
        this.processorTaskService = processorTaskService;
        this.documentEventLog = documentEventLog;
        this.nodeService = nodeService;
        this.nodeInfo = nodeInfo;
        this.webTargetFactory = webTargetFactory;
        this.processorTaskManager = processorTaskManager;
    }

    @Override
    public ResultPage<ProcessorTask> find(final ExpressionCriteria criteria) {
        ResultPage<ProcessorTask> result;

        final Query.Builder<Void> queryBuilder = Query.builder();
        StroomEventLoggingUtil.appendExpression(queryBuilder, criteria.getExpression());
        final Query query = queryBuilder.build();

        try {
            result = processorTaskService.find(criteria);
            documentEventLog.search(
                    criteria.getClass().getSimpleName(),
                    query,
                    ProcessorTask.class.getSimpleName(),
                    result.getPageResponse(),
                    null);
        } catch (final RuntimeException e) {
            documentEventLog.search(
                    criteria.getClass().getSimpleName(),
                    query,
                    ProcessorTask.class.getSimpleName(),
                    null,
                    e);
            throw e;
        }

        return result;
    }

    @Override
    public ResultPage<ProcessorTaskSummary> findSummary(final ExpressionCriteria criteria) {
        ResultPage<ProcessorTaskSummary> result;

        final Query.Builder<Void> queryBuilder = Query.builder();
        StroomEventLoggingUtil.appendExpression(queryBuilder, criteria.getExpression());
        final Query query = queryBuilder.build();

        try {
            result = processorTaskService.findSummary(criteria);
            documentEventLog.search(
                    criteria.getClass().getSimpleName(),
                    query,
                    ProcessorTaskSummary.class.getSimpleName(),
                    result.getPageResponse(),
                    null);
        } catch (final RuntimeException e) {
            documentEventLog.search(
                    criteria.getClass().getSimpleName(),
                    query,
                    ProcessorTaskSummary.class.getSimpleName(),
                    null,
                    e);
            throw e;
        }

        return result;
    }

    @Override
    public ProcessorTaskList assignTasks(final String nodeName, final AssignTasksRequest request) {
        // If this is the node that was contacted then just return the latency we have incurred within this method.
        if (NodeCallUtil.shouldExecuteLocally(nodeInfo, nodeName)) {
            return processorTaskManager.assignTasks(request.getNodeName(), request.getCount());

        } else {
            final String url = NodeCallUtil.getBaseEndpointUrl(nodeInfo, nodeService, nodeName)
                    + ResourcePaths.buildAuthenticatedApiPath(
                    ProcessorTaskResource.BASE_PATH,
                    ProcessorTaskResource.ASSIGN_TASKS_PATH_PART,
                    nodeName);

            try {
                final Response response = webTargetFactory
                        .create(url)
                        .request(MediaType.APPLICATION_JSON)
                        .post(Entity.json(request));
                if (response.getStatus() != 200) {
                    throw new WebApplicationException(response);
                }
                return response.readEntity(ProcessorTaskList.class);
            } catch (Throwable e) {
                throw NodeCallUtil.handleExceptionsOnNodeCall(nodeName, url, e);
            }
        }
    }

    @Override
    public Boolean abandonTasks(final String nodeName, final ProcessorTaskList request) {
        // If this is the node that was contacted then just return the latency we have incurred within this method.
        if (NodeCallUtil.shouldExecuteLocally(nodeInfo, nodeName)) {
            return processorTaskManager.abandonTasks(request);

        } else {
            final String url = NodeCallUtil.getBaseEndpointUrl(nodeInfo, nodeService, nodeName)
                    + ResourcePaths.buildAuthenticatedApiPath(
                    ProcessorTaskResource.BASE_PATH,
                    ProcessorTaskResource.ABANDON_TASKS_PATH_PART,
                    nodeName);

            try {
                final Response response = webTargetFactory
                        .create(url)
                        .request(MediaType.APPLICATION_JSON)
                        .put(Entity.json(request));
                if (response.getStatus() != 200) {
                    throw new WebApplicationException(response);
                }
                return response.readEntity(Boolean.class);
            } catch (Throwable e) {
                throw NodeCallUtil.handleExceptionsOnNodeCall(nodeName, url, e);
            }
        }
    }
}

@@ -775,24 +775,132 @@
 oggingUtil;%0A
+import stroom.event.logging.rs.api.AutoLogged;%0Aimport stroom.event.logging.rs.api.AutoLogged.OperationType;%0A
 import stroo
@@ -920,24 +920,24 @@
 deCallUtil;%0A
-
 import stroo
@@ -1626,16 +1626,28 @@
 ponse;%0A%0A
+@AutoLogged%0A
 class Pr
@@ -2747,32 +2747,79 @@
 %0A%0A    @Override%0A
+    @AutoLogged(OperationType.MANUALLY_LOGGED)%0A
     public Resul
@@ -3794,32 +3794,79 @@
 %0A%0A    @Override%0A
+    @AutoLogged(OperationType.MANUALLY_LOGGED)%0A
     public Resul
@@ -4883,32 +4883,72 @@
 %0A%0A    @Override%0A
+    @AutoLogged(OperationType.UNLOGGED)%0A
     public Proce
@@ -6211,32 +6211,32 @@
        %7D%0A    %7D%0A%0A
-
     @Override%0A  
@@ -6229,24 +6229,64 @@
   @Override%0A
+    @AutoLogged(OperationType.UNLOGGED)%0A
     public B

Add @Autologged towards standards