package io.github.tcdl.msb.examples;

import io.github.tcdl.msb.api.MessageTemplate;
import io.github.tcdl.msb.api.MsbContext;
import io.github.tcdl.msb.api.MsbContextBuilder;
import io.github.tcdl.msb.api.RequestOptions;
import io.github.tcdl.msb.api.Requester;
import io.github.tcdl.msb.api.Responder;
import io.github.tcdl.msb.api.message.payload.Payload;
import io.github.tcdl.msb.examples.payload.Request;

import javax.script.ScriptException;
import java.io.FileNotFoundException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * Microservice which is listening for incoming messages, creates requests to another microservices(
 * data-extractor, airport-extractor, resort-extractor), concatenates responses and returns result response
 */
public class FacetsAggregator {

    public static void main(String[] args) throws ScriptException, FileNotFoundException, NoSuchMethodException {

        MsbContext msbContext = new MsbContextBuilder()
                .enableChannelMonitorAgent(true)
                .enableShutdownHook(true)
                .build();

        MessageTemplate options = new MessageTemplate();
        final String namespace = "search:aggregator:facets:v1";

        msbContext.getObjectFactory().createResponderServer(namespace, options, (Request facetsRequest, Responder responder) -> {

            String q = facetsRequest.getQuery().getQ();

            if (q == null) {
                Payload responsePayload = new Payload.Builder()
                        .withStatusCode(400)
                        .build();
                responder.send(responsePayload);
            } else if (q.isEmpty()) {
                ResponseBodyAny responseBodyAny = new ResponseBodyAny();
                Facet facet = new Facet();
                facet.setProbability(1f);

                Map<String, Object> map = new HashMap<>();
                map.put("depAirport", 0);
                map.put("resortCode", "any");
                facet.setParams(map);

                responseBodyAny.setFacets(Arrays.asList(facet));

                Payload responsePayloadAny = new Payload.Builder<Object, Object, Object, ResponseBodyAny>()
                        .withStatusCode(200)
                        .withBody(responseBodyAny)
                        .build();

                responder.send(responsePayloadAny);
            } else {
                RequestOptions requestOptions = new RequestOptions.Builder()
                        .withWaitForResponses(1)
                        .withAckTimeout(200)
                        .withResponseTimeout(600)
                        .build();

                Requester<Payload> requester = msbContext.getObjectFactory().createRequester("search:parsers:facets:v1",
                        requestOptions, Payload.class);

                final String[] result = {""};

                requester.onResponse(response -> {
                    System.out.println(">>> RESPONSE: " + response);
                    result[0] +=response;
                });

                List<Payload> responses = new LinkedList<>();
                requester.onResponse(response -> responses.add(response))
                .onEnd(end -> {
                    for (Payload payload : responses)
                        System.out.println(">>> MESSAGE: " + payload);

                    Payload responsePayload = new Payload.Builder<Object, Object, Object, String>()
                            .withStatusCode(200)
                            .withBody(result[0])
                            .build();

                    responder.send(responsePayload);
                });

                requester.publish(facetsRequest, responder.getOriginalMessage());
            }
        }, Request.class).listen();
    }

    private static class ResponseBodyAny {
        private List<Facet> facets;

        public List<Facet> getFacets() {
            return facets;
        }

        public void setFacets(List<Facet> facets) {
            this.facets = facets;
        }
    }

    private static class Facet {
        private float probability;
        private int[] offsets = {};
        private Map<String, Object> params;
        private String[] mappings = {};

        public float getProbability() {
            return probability;
        }

        public void setProbability(float probability) {
            this.probability = probability;
        }

        public int[] getOffsets() {
            return offsets;
        }

        public void setOffsets(int[] offsets) {
            this.offsets = offsets;
        }

        public Map<String, Object> getParams() {
            return params;
        }

        public void setParams(Map<String, Object> params) {
            this.params = params;
        }

        public String[] getMappings() {
            return mappings;
        }

        public void setMappings(String[] mappings) {
            this.mappings = mappings;
        }
    }
}

@@ -502,17 +502,20 @@
 il.Array
-s
+List
 ;%0Aimport
@@ -525,23 +525,27 @@
 va.util.
-HashMap
+Collections
 ;%0Aimport
@@ -555,26 +555,23 @@
 va.util.
-LinkedList
+HashMap
 ;%0Aimport
@@ -2109,17 +2109,29 @@
 ets(
-Arrays.as
+Collections.singleton
 List
@@ -2954,235 +2954,80 @@
     
-requester.onResponse(response -%3E %7B%0A                    System.out.println(%22%3E%3E%3E RESPONSE: %22 + response);%0A                    result%5B0%5D +=response;%0A                %7D);%0A%0A                List%3CPayload%3E responses = new Linked
+List%3CPayload%3E responses = Collections.synchronizedList(new Array
 List%3C%3E()
 ;%0A  
@@ -3018,24 +3018,25 @@
 rrayList%3C%3E()
+)
 ;%0A          
@@ -3074,35 +3074,14 @@
 onse
- -%3E responses.add(response)
+s::add
 )%0A  
@@ -3163,16 +3163,18 @@
 sponses)
+ %7B
 %0A       
@@ -3236,16 +3236,84 @@
 ayload);
+%0A                        result%5B0%5D += payload;%0A                    %7D
 %0A%0A      

Fix for FacetsAggregator