/*******************************************************************************
 * Copyright (C) 2017 Push Technology Ltd.
 *
 * 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 com.pushtechnology.adapters.rest.adapter;

import static com.pushtechnology.adapters.rest.endpoints.EndpointType.from;
import static com.pushtechnology.adapters.rest.endpoints.EndpointType.inferFromContentType;

import java.util.function.Consumer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.pushtechnology.adapters.rest.endpoints.EndpointType;
import com.pushtechnology.adapters.rest.model.latest.EndpointConfig;
import com.pushtechnology.adapters.rest.model.latest.ServiceConfig;
import com.pushtechnology.adapters.rest.polling.EndpointClient;
import com.pushtechnology.adapters.rest.polling.EndpointResponse;
import com.pushtechnology.adapters.rest.publication.PublishingClient;
import com.pushtechnology.adapters.rest.services.ServiceSession;
import com.pushtechnology.adapters.rest.topic.management.TopicManagementClient;

/**
 * Initialise the endpoint for a service.
 *
 * @author Push Technology Limited
 */
/*package*/ final class InitialiseEndpoint implements Consumer<EndpointConfig> {
    private static final Logger LOG = LoggerFactory.getLogger(InitialiseEndpoint.class);
    private final EndpointClient endpointClient;
    private final TopicManagementClient topicManagementClient;
    private final PublishingClient publishingClient;
    private final ServiceConfig service;
    private final ServiceSession serviceSession;

    /**
     * Constructor.
     */
    /*package*/ InitialiseEndpoint(
            EndpointClient endpointClient,
            TopicManagementClient topicManagementClient,
            PublishingClient publishingClient,
            ServiceConfig service,
            ServiceSession serviceSession) {

        this.endpointClient = endpointClient;
        this.topicManagementClient = topicManagementClient;
        this.publishingClient = publishingClient;
        this.service = service;
        this.serviceSession = serviceSession;
    }

    @Override
    public void accept(EndpointConfig endpointConfig) {
        endpointClient.request(
            service,
            endpointConfig).thenAccept(result -> {
                final EndpointConfig resolvedConfig = resolveEndpointConfig(endpointConfig, result);
                final EndpointResponse response = new ValidateContentType().apply(result, resolvedConfig);
                createHandler(from(resolvedConfig.getProduces()), resolvedConfig).accept(response);
            }).exceptionally(e -> {
                LOG.warn("Endpoint {} not initialised. First request failed.", endpointConfig);
                return null;
            });
    }

    private EndpointConfig resolveEndpointConfig(EndpointConfig endpointConfig, EndpointResponse response) {
        final String produces = endpointConfig.getProduces();
        if ("auto".equals(produces)) {
            return inferEndpointConfig(inferFromContentType(response.getHeader("content-type")), endpointConfig);
        }
        else {
            return endpointConfig;
        }
    }

    private EndpointConfig inferEndpointConfig(EndpointType<?> endpointType, EndpointConfig endpointConfig) {
        return EndpointConfig
            .builder()
            .name(endpointConfig.getName())
            .topicPath(endpointConfig.getTopicPath())
            .url(endpointConfig.getUrl())
            .produces(endpointType.getIdentifier())
            .build();
    }

    private <T> Consumer<EndpointResponse> createHandler(
            EndpointType<T> endpointType,
            EndpointConfig endpointConfig) {
        return response -> {
            final AddTopicForEndpoint<T> handler = new AddTopicForEndpoint<>(
                topicManagementClient,
                service,
                endpointConfig,
                publishingClient.createUpdateContext(
                    service,
                    endpointConfig,
                    endpointType.getDataType()),
                new AddEndpointToServiceSession(endpointConfig, serviceSession));

            try {
                handler.accept(endpointType.getParser().transform(response), null);
            }
            catch (Exception e) {
                handler.accept(null, e);
            }
        };
    }
}

@@ -2764,17 +2764,8 @@
 ient
-.request(
 %0A   
@@ -2773,36 +2773,33 @@
         
-service,%0A           
+.request(service,
  endpoin
@@ -2806,16 +2806,29 @@
 tConfig)
+%0A            
 .thenAcc
@@ -3067,29 +3067,30 @@
         
-createHandler
+handleResponse
 (from(re
@@ -3136,17 +3136,10 @@
 nfig
-).accept(
+, 
 resp
@@ -4134,48 +4134,27 @@
 %3CT%3E 
-Consumer%3CEndpointResponse%3E createHandler
+void handleResponse
 (%0A  
@@ -4226,35 +4226,33 @@
 g endpointConfig
-) %7B
+,
 %0A        return 
@@ -4244,22 +4244,36 @@
         
-return
+    EndpointResponse
  respons
@@ -4273,19 +4273,17 @@
 response
- -%3E
+)
  %7B%0A     
@@ -4281,28 +4281,24 @@
 ) %7B%0A        
-  
-  
 final AddTop
@@ -4363,20 +4363,16 @@
         
-    
 topicMan
@@ -4390,36 +4390,32 @@
 nt,%0A            
-   
- 
 service,%0A       
@@ -4399,36 +4399,32 @@
        service,%0A
-    
             endp
@@ -4427,36 +4427,32 @@
 endpointConfig,%0A
-    
             publ
@@ -4493,36 +4493,32 @@
                 
-    
 service,%0A       
@@ -4502,36 +4502,32 @@
        service,%0A
-    
                 
@@ -4550,36 +4550,32 @@
                 
- 
-   
 endpointType.get
@@ -4587,20 +4587,16 @@
 ype()),%0A
-    
         
@@ -4678,22 +4678,14 @@
     
- 
-   
 try %7B%0A
-    
     
@@ -4764,34 +4764,26 @@
 l);%0A        
-    %7D%0A    
+%7D%0A
         catc
@@ -4804,36 +4804,32 @@
 ) %7B%0A            
-  
-  
 handler.accept(n
@@ -4849,24 +4849,9 @@
     
-    %7D%0A        %7D;
+%7D
 %0A   

Simplify InitialiseEndpoint by removing Consumer.