/**
 *
 */
package com.catpeds.crawler.pawpeds;

import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Optional;
import java.util.function.Function;

import javax.inject.Inject;

import org.jsoup.nodes.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.catpeds.crawler.jsoup.DocumentRepository;
import com.catpeds.model.Pedigree;
import com.catpeds.model.PedigreeCriteria;

/**
 * {@link PawpedsPedigreeRepository} default implementation.
 *
 * @author padriano
 *
 */
class PawpedsPedigreeRepositoryImpl implements PawpedsPedigreeRepository {

	private static final Logger LOGGER = LoggerFactory.getLogger(PawpedsPedigreeRepositoryImpl.class);

	private DocumentRepository documentRepository;
	private PawpedsUrlService pawpedsUrlService;
	private PawpedsDocumentParser pawpedsSearchResultParser;

	@Inject
	PawpedsPedigreeRepositoryImpl(DocumentRepository documentRepository, PawpedsUrlService pawpedsUrlService,
			PawpedsDocumentParser pawpedsSearchResultParser) {
		this.documentRepository = documentRepository;
		this.pawpedsUrlService = pawpedsUrlService;
		this.pawpedsSearchResultParser = pawpedsSearchResultParser;
	}

	<T> T getAndParsePawpedsDocument(String url,
			Function<Document, T> parserFunction) {
		return getAndParsePawpedsDocument(url, parserFunction, null);
	}

	<T> T getAndParsePawpedsDocument(String url,
			Function<Document, T> parserFunction, T defaultResult) {
		try {
			Optional<Document> searchDocument = documentRepository.get(url);
			if (searchDocument.isPresent()) {
				// successful retrieving the document at first try
				return parserFunction.apply(searchDocument.get());
			}
			// this means that there was a timeout. retrying...
			searchDocument = documentRepository.get(url);
			if (searchDocument.isPresent()) {
				return parserFunction.apply(searchDocument.get());
			}

			LOGGER.warn("Timeout retrieving document from {}", url);

		} catch (IOException e) {
			LOGGER.error("Unexpected exception occurred", e);
		}

		return defaultResult;
	}

	/**
	 * @see com.catpeds.crawler.pawpeds.PawpedsPedigreeRepository#findAll(com.catpeds.model.PedigreeCriteria)
	 */
	@Override
	public Collection<Pedigree> findAll(PedigreeCriteria criteria) {
		String searchUrl = pawpedsUrlService.getAdvancedSearchUrl(criteria);
		return getAndParsePawpedsDocument(searchUrl, pawpedsSearchResultParser::parseSearch, Arrays.asList());
	}

	/**
	 * @see com.catpeds.crawler.pawpeds.PawpedsPedigreeRepository#findAllOffspring(long)
	 */
	@Override
	public Collection<Pedigree> findAllOffspring(long id) {
		String offspringSearchUrl = pawpedsUrlService.getOffspringsSearchUrl(id);
		return getAndParsePawpedsDocument(offspringSearchUrl, pawpedsSearchResultParser::parseOffsprings,
				Arrays.asList());
	}

	/**
	 * @see com.catpeds.crawler.pawpeds.PawpedsPedigreeRepository#findOne(long)
	 */
	@Override
	public Optional<Pedigree> findOne(long id) {
		// get pedigree information
		String offspringSearchUrl = pawpedsUrlService.getPedigreeUrl(id);
		Optional<Pedigree> pedigree = getAndParsePawpedsDocument(offspringSearchUrl, pawpedsSearchResultParser::parsePedigree,
				Optional.empty());

		// populate with the offspring list
		if (pedigree.isPresent()) {
			findAllOffspring(id).stream().mapToLong(Pedigree::getId).forEach(pedigree.get()::addOffspring);
		}

		return pedigree;
	}
}

@@ -2253,24 +2253,78 @@
 criteria) %7B%0A
+%09%09LOGGER.info(%22findAll with criteria %7B%7D%22, criteria);%0A%0A
 %09%09String sea
@@ -2382,16 +2382,73 @@
 teria);%0A
+%09%09LOGGER.debug(%22URL for advanced search %7B%7D%22, searchUrl);%0A
 %09%09return
@@ -2712,16 +2712,67 @@
 g id) %7B%0A
+%09%09LOGGER.info(%22findAllOffspring with id %7B%7D%22, id);%0A%0A
 %09%09String
@@ -2839,16 +2839,84 @@
 rl(id);%0A
+%09%09LOGGER.debug(%22URL for offsprings search %7B%7D%22, offspringSearchUrl);%0A
 %09%09return
@@ -3177,16 +3177,58 @@
 g id) %7B%0A
+%09%09LOGGER.info(%22findOne with id %7B%7D%22, id);%0A%0A
 %09%09// get
@@ -3254,33 +3254,32 @@
 on%0A%09%09String 
-offspring
+pedigree
 SearchUrl = 
@@ -3316,16 +3316,81 @@
 rl(id);%0A
+%09%09LOGGER.debug(%22URL for pedigree search %7B%7D%22, pedigreeSearchUrl);%0A
 %09%09Option
@@ -3436,33 +3436,32 @@
 edsDocument(
-offspring
+pedigree
 SearchUrl, p

Add logging to the repository implementation to save inputs