package eu.eudat.logic.managers;

import eu.eudat.logic.proxy.config.ExternalUrlCriteria;
import eu.eudat.logic.utilities.helpers.ListHelper;
import eu.eudat.models.data.external.ProjectsExternalSourcesModel;
import eu.eudat.models.data.project.Project;
import eu.eudat.data.query.items.item.project.ProjectCriteriaRequest;
import eu.eudat.logic.builders.model.models.ProjectBuilder;
import eu.eudat.logic.proxy.config.exceptions.HugeResultSet;
import eu.eudat.logic.proxy.config.exceptions.NoURLFound;
import eu.eudat.logic.proxy.fetching.RemoteFetcher;
import eu.eudat.logic.services.ApiContext;
import eu.eudat.models.data.external.ExternalSourcesItemModel;
import eu.eudat.models.data.security.Principal;
import eu.eudat.queryable.QueryableList;
import org.springframework.stereotype.Component;

import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Component
public class ProjectManager {

	private ApiContext apiContext;
	private RemoteFetcher remoteFetcher;
	private ListHelper listHelper;

	public ProjectManager(ApiContext apiContext, ListHelper listHelper) {
		this.apiContext = apiContext;
		this.remoteFetcher = apiContext.getOperationsContext().getRemoteFetcher();
		this.listHelper = listHelper;
	}

	public List<Project> getCriteriaWithExternal(ProjectCriteriaRequest projectCriteria, Principal principal) throws HugeResultSet, NoURLFound {
		eu.eudat.data.entities.UserInfo userInfo = new eu.eudat.data.entities.UserInfo();
		userInfo.setId(principal.getId());
		projectCriteria.getCriteria().setReference("dmp:");
		QueryableList<eu.eudat.data.entities.Project> items = apiContext.getOperationsContext().getDatabaseRepository().getProjectDao().getWithCritetia(projectCriteria.getCriteria());
		QueryableList<eu.eudat.data.entities.Project> authItems = apiContext.getOperationsContext().getDatabaseRepository().getProjectDao().getAuthenticated(items, userInfo);
		List<Project> projects = authItems.select(item -> new Project().fromDataModel(item));
		ExternalUrlCriteria externalUrlCriteria = new ExternalUrlCriteria(projectCriteria.getCriteria().getLike());
		List<Map<String, String>> remoteRepos = remoteFetcher.getProjects(externalUrlCriteria);
		ProjectsExternalSourcesModel projectsExternalSourcesModel = new ProjectsExternalSourcesModel().fromExternalItem(remoteRepos);
		for (ExternalSourcesItemModel externalListingItem : projectsExternalSourcesModel) {
			eu.eudat.models.data.project.Project project = apiContext.getOperationsContext().getBuilderFactory().getBuilder(ProjectBuilder.class)
					.reference(externalListingItem.getRemoteId()).label(externalListingItem.getName())
					.description(externalListingItem.getDescription()).uri(externalListingItem.getUri())
					.abbreviation(externalListingItem.getAbbreviation()).status(eu.eudat.data.entities.Project.Status.fromInteger(0))
					.key(externalListingItem.getKey())
					.source(externalListingItem.getTag())
					.build();

			projects.add(project);
		}
		projects.sort(Comparator.comparing(Project::getLabel));
		projects = projects.stream().filter(listHelper.distinctByKey(Project::getLabel)).collect(Collectors.toList());
		return projects;
	}
}
