package eu.dnetlib.lbs.tests;

import java.util.Arrays;

import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import eu.dnetlib.broker.objects.OpenAireEventPayload;
import eu.dnetlib.broker.objects.Publication;
import eu.dnetlib.lbs.elasticsearch.Event;
import eu.dnetlib.lbs.elasticsearch.EventRepository;
import eu.dnetlib.lbs.openaire.AdvQueryObject;
import eu.dnetlib.lbs.openaire.ElasticSearchQueryUtils;
import eu.dnetlib.lbs.openaire.Range;

@Ignore
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:/applicationContext-test-queries.xml" })
public class OpenaireQueriesTest {

	private static final String indexName = Event.class.getAnnotation(Document.class).indexName();
	private static final String indexType = Event.class.getAnnotation(Document.class).type();

	@Autowired
	private EventRepository eventRepository;

	@Before
	public void setUp() throws Exception {

	}

	@Test
	@Ignore
	public void testAdvancedShowEvents() {

		final AdvQueryObject qObj = new AdvQueryObject();
		qObj.setDatasource("INRIA a CCSD electronic archive server");
		qObj.setTopic("ENRICH/MORE/PID");
		qObj.setTitles(Arrays.asList("Aerosol", "profiles"));
		qObj.setAuthors(Arrays.asList("Arnaud", "Kulmala", "Morten"));
		qObj.setSubjects(Arrays.asList("satellite", "cloud"));
		qObj.setTrust(new Range("0", "1"));

		final BoolQueryBuilder mapQuery = QueryBuilders.boolQuery();
		ElasticSearchQueryUtils.addMapCondition(mapQuery, "map.target_datasource_name", qObj.getDatasource());
		ElasticSearchQueryUtils.addMapCondition(mapQuery, "map.target_publication_title", qObj.getTitles());
		ElasticSearchQueryUtils.addMapCondition(mapQuery, "map.target_publication_author_list", qObj.getAuthors());
		ElasticSearchQueryUtils.addMapCondition(mapQuery, "map.target_publication_subject_list", qObj.getSubjects());
		ElasticSearchQueryUtils.addMapConditionForTrust(mapQuery, "map.trust", qObj.getTrust());
		ElasticSearchQueryUtils.addMapConditionForDates(mapQuery, "map.target_dateofacceptance", qObj.getDates());

		final SearchQuery searchQuery = new NativeSearchQueryBuilder()
				.withQuery(QueryBuilders.boolQuery()
						.must(QueryBuilders.matchQuery("topic", qObj.getTopic()))
						.must(QueryBuilders.nestedQuery("map", mapQuery, ScoreMode.None)))
				.withSearchType(SearchType.DEFAULT)
				.withIndices(indexName)
				.withTypes(indexType)
				.withFields("payload")
				.withPageable(PageRequest.of(0, 10))
				.build();

		final Page<Event> page = this.eventRepository.search(searchQuery);

		page.getContent().stream()
				.map(Event::getPayload)
				.map(OpenAireEventPayload::fromJSON)
				.map(OpenAireEventPayload::getPublication)
				.map(Publication::getTitles)
				.forEach(System.out::println);

	}

}
