package eu.dnetlib.wds.resolver;

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import eu.dnetlib.miscutils.collections.Pair;
import eu.dnetlib.pid.resolver.AbstractPIDResolver;
import eu.dnetlib.pid.resolver.model.ObjectProvenance;
import eu.dnetlib.pid.resolver.model.ObjectType;
import eu.dnetlib.pid.resolver.model.PID;
import eu.dnetlib.pid.resolver.model.SubjectType;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

import java.util.*;

public class DLIResolver extends AbstractPIDResolver {

    private static String INDEX_URL = "http://ip-90-147-167-27.ct1.garrservices.it:9200/dli_shadow/object/_search?pretty";

    @Override
    protected boolean canResolvePid(String pidType) {
        return StringUtils.isNotEmpty(pidType);
    }

    public WDSResolvedObject resolve(final String pid, final String pidType) {
        final RestTemplate restTemplate = new RestTemplate();

        final ResponseEntity<JsonObject> jsonObjectResponseEntity = restTemplate.postForEntity(INDEX_URL, createJson(pid, pidType), JsonObject.class);
        final JsonObject hits = jsonObjectResponseEntity.getBody().getAsJsonObject("hits");
        final int total = hits.get("total").getAsInt();
        if (total > 0) {
            final JsonArray results = hits.getAsJsonArray("hits");
            return parseDLIResponse(results.get(0).getAsJsonObject());
        }
        return null;
    }


    private WDSResolvedObject parseDLIResponse(final JsonObject input) {
        final WDSResolvedObject result = new WDSResolvedObject();
        final JsonObject source = input.getAsJsonObject("_source");
        if (source == null || source.isJsonNull())
            return null;
        final JsonArray localIdentifiers = source.getAsJsonArray("localIdentifier");
        if (localIdentifiers == null || localIdentifiers.isJsonNull())
            return null;
        localIdentifiers.forEach(it -> result.addPid(new PID(it.getAsJsonObject().get("id").getAsString(), it.getAsJsonObject().get("type").getAsString())));
        final String typology = source.get("typology").getAsString();
        if (typology.equals("publication") || typology.equals("dataset")) {
            result.setType(ObjectType.valueOf(typology));
        } else {
            return null;
        }
        result.setTitles(getArrayFromJson("title", source));
        result.setAuthors(getArrayFromJson("author", source));
        final List<String> date = getArrayFromJson("date", source);
        Map<String, String> d = new HashMap<>();
        if (date != null && date.size() > 0) {
            d.put("unknown", date.get(0));
        }
        result.setDates(d);
        final String description = source.get("abstract") != null ? source.get("abstract").getAsString() : null;
        if (description != null && StringUtils.isNotEmpty(description))
            result.addDescription(new Pair<>("unknown", description));
        final JsonArray subjectArray = source.getAsJsonArray("subject");
        if (subjectArray != null && !subjectArray.isJsonNull()) {
            subjectArray.forEach(it -> result.addSubject(new SubjectType(it.getAsJsonObject().get("scheme").getAsString(), it.getAsJsonObject().get("value").getAsString())));
        }

        final JsonArray publisherArray = source.getAsJsonArray("publisher");

        if (publisherArray != null && !publisherArray.isJsonNull()) {
            publisherArray.forEach(it -> result.setPublisher(it.getAsString()));
        }
        result.setDatasourceProvenance(Collections.singletonList(new ObjectProvenance().setDatasource("Data Literature Interlinking").setDatasourceId("wds_________::dli")));
        return result;
    }


    private List<String> getArrayFromJson(final String key, final JsonObject source) {

        final List<String> result = new ArrayList<>();
        final JsonArray inputArray = source.getAsJsonArray(key);
        if (inputArray != null && !inputArray.isJsonNull()) {
            inputArray.forEach(it -> {
                if (StringUtils.isNotEmpty(it.getAsString())) result.add(it.getAsString());

            });
        }
        return result;

    }


    private JsonObject createJson(final String pid, final String pidType) {

        final JsonObject root = new JsonObject();

        final JsonObject nested = new JsonObject();
        final JsonObject n1 = new JsonObject();
        final JsonObject nestedQuery = new JsonObject();
        final JsonObject boolQuery = new JsonObject();
        final JsonArray mustArray = new JsonArray();

        final JsonObject firstMatch = new JsonObject();
        final JsonObject firstMatchId = new JsonObject();
        final JsonObject secondMatch = new JsonObject();
        final JsonObject secondMatchType = new JsonObject();


        root.add("query", n1);
        n1.add("nested", nested);
        nested.addProperty("path", "localIdentifier");
        nested.add("query", nestedQuery);
        nestedQuery.add("bool", boolQuery);
        boolQuery.add("must", mustArray);

        mustArray.add(firstMatch);
        mustArray.add(secondMatch);

        firstMatch.add("match", firstMatchId);
        secondMatch.add("match", secondMatchType);

        firstMatchId.addProperty("localIdentifier.id", pid.toLowerCase().trim());
        secondMatchType.addProperty("localIdentifier.type", pidType.toLowerCase().trim());


        return root;


    }

}
