package com.telephoners.krakyournet.ctf.repositories;

import com.telephoners.krakyournet.ctf.beans.Solution;
import com.telephoners.krakyournet.ctf.beans.Team;
import com.telephoners.krakyournet.ctf.beans.tasks.Task;
import org.mongodb.morphia.Datastore;

import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

@Singleton
public class SolutionsRepository extends Repository<Solution>
{
    @Inject
    public SolutionsRepository(Datastore datastore)
    {
        super(datastore);
    }

    public Map<Integer, List<String>> getTeamSolutions(Team team)
    {
        //todo: do not identify team by name? conflict in team ids?
        return datastore.createQuery(Solution.class)
                .filter("team.name",team.getName()).asList()
                .stream()
                .collect(Collectors.groupingBy(new Function<Solution, Task>()
                {
                    @Override
                    public Task apply(Solution solution1)
                    {
                        return solution1.getTask();
                    }
                }))
                .entrySet()
                .stream()
                .collect(Collectors.toMap(
                        taskSolutions -> taskSolutions.getKey().getLevel(),
                        taskSolutions -> taskSolutions.getValue().stream()
                                .map(solution -> solution.getFlag().getDescription()).collect(Collectors.toList())
                ));
    }

    //todo: use datastore filter
    public boolean exists(Solution solution)
    {
        //todo: refactor, ugly ;(
        String value = solution.getFlag().getValue();
        Optional<Solution> matchedSolution = getAll().stream()
                .filter(new Predicate<Solution>()
                {
                    @Override
                    public boolean test(Solution solution)
                    {
                        //todo: compare flags, not flag values
                        return solution.getFlag().getValue().equals(value);
                    }
                })
                .findFirst();
        return matchedSolution.isPresent();
    }
}