package no.uio.ifi.trackfind.backend.services;

import com.google.gson.Gson;
import no.uio.ifi.trackfind.backend.configuration.TrackFindProperties;
import no.uio.ifi.trackfind.backend.dao.Dataset;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.function.Function;

/**
 * Service for querying remote GSuite service for performing JSON to GSuite conversion.
 */
// TODO: cover with tests
@Service
public class GSuiteService implements Function<Collection<Dataset>, String> {

    private TrackFindProperties properties;
    private Gson gson;
    private SchemaService schemaService;
    private RestTemplate restTemplate;

    /**
     * Convert datasets to GSuite.
     *
     * @param datasets Datasets to convert.
     * @return GSuite string.
     */
    @SuppressWarnings("unchecked")
    @Override
    public String apply(Collection<Dataset> datasets) {
        sortJSON(datasets);
        HttpEntity<Collection<Dataset>> request = new HttpEntity<>(datasets);
        return restTemplate.postForObject("http://gsuite/togsuite", request, String.class);
    }

    protected void sortJSON(Collection<Dataset> datasets) {
        for (Dataset dataset : datasets) {
            dataset.setFairContent(sortJSON(dataset.getFairContent()));
        }
    }

    protected String sortJSON(String fairContent) {
        Map mapContent = gson.fromJson(fairContent, Map.class);
        mapContent = sortMap("", mapContent);
        return gson.toJson(mapContent);
    }

    @SuppressWarnings("unchecked")
    protected Map sortMap(String path, Map mapContent) {
        TreeMap sortedMap = new TreeMap((o1, o2) -> {
            String key1 = path + o1.toString();
            String key2 = path + o2.toString();
            List<String> attributes = schemaService.getAttributes();
            String fullKey1 = attributes.stream().filter(a -> a.startsWith(key1)).findFirst().orElse(null);
            String fullKey2 = attributes.stream().filter(a -> a.startsWith(key2)).findFirst().orElse(null);
            long index1 = fullKey1 == null ? Long.MAX_VALUE : attributes.indexOf(fullKey1);
            long index2 = fullKey2 == null ? Long.MAX_VALUE : attributes.indexOf(fullKey2);
            return Long.compare(index1, index2);
        });
        for (Object key : mapContent.keySet()) {
            Object value = mapContent.get(key);
            if (value instanceof Map) {
                sortedMap.put(key, sortMap(path + key + properties.getLevelsSeparator(), (Map) value));
            } else {
                sortedMap.put(key, value);
            }
        }
        return sortedMap;
    }

    @Autowired
    public void setProperties(TrackFindProperties properties) {
        this.properties = properties;
    }

    @Autowired
    public void setGson(Gson gson) {
        this.gson = gson;
    }

    @Autowired
    public void setSchemaService(SchemaService schemaService) {
        this.schemaService = schemaService;
    }

    @Autowired
    public void setRestTemplate(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

}

@@ -190,16 +190,61 @@
 ataset;%0A
+import org.apache.commons.lang3.StringUtils;%0A
 import o
@@ -1729,24 +1729,82 @@
 apContent);%0A
+        System.out.println(%22mapContent = %22 + mapContent);%0A
         retu
@@ -1827,24 +1827,24 @@
 apContent);%0A
-
     %7D%0A%0A    @
@@ -2242,36 +2242,34 @@
 dFirst().orElse(
-null
+%22%22
 );%0A            S
@@ -2356,20 +2356,18 @@
 .orElse(
-null
+%22%22
 );%0A     
@@ -2377,88 +2377,368 @@
     
-long index1 = fullKey1 == null ? Long.MAX_VALUE : attributes.indexOf(fullKey1);%0A
+if (StringUtils.isEmpty(fullKey1) %7C%7C StringUtils.isEmpty(fullKey2)) %7B%0A                if (StringUtils.isEmpty(fullKey1) && StringUtils.isEmpty(fullKey2)) %7B%0A                    return fullKey1.compareTo(fullKey2);%0A                %7D else %7B%0A                    return Long.compare(fullKey1.length(), fullKey2.length());%0A                %7D%0A            %7D else %7B%0A    
     
@@ -2759,47 +2759,71 @@
 ndex
-2 = fullKey2 == null ? Long.MAX_VALUE :
+1 = attributes.indexOf(fullKey1);%0A                long index2 =
  att
@@ -2841,32 +2841,36 @@
 exOf(fullKey2);%0A
+    
             retu
@@ -2898,24 +2898,38 @@
 1, index2);%0A
+            %7D%0A
         %7D);%0A

Fix ordering in GSuiteService.