package com.telephoners.krakyournet.ctf.resources;

import com.telephoners.krakyournet.ctf.objects.Solution;
import com.telephoners.krakyournet.ctf.objects.Team;
import com.telephoners.krakyournet.ctf.objects.User;
import com.telephoners.krakyournet.ctf.objects.tasks.Task;
import com.telephoners.krakyournet.ctf.repositories.SolutionsRepository;
import com.telephoners.krakyournet.ctf.repositories.TasksRepository;
import com.telephoners.krakyournet.ctf.repositories.TeamsRepository;
import io.dropwizard.auth.Auth;

import javax.inject.Inject;
import javax.inject.Singleton;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;

@Singleton
@Path(value = "/solutions")
@Produces(MediaType.APPLICATION_JSON)
public class SolutionsResource
{
    private TeamsRepository teamsRepository;
    private SolutionsRepository solutionsRepository;
    private TasksRepository tasksRepository;

    @Inject
    public SolutionsResource(SolutionsRepository solutionsRepository, TasksRepository tasksRepository,
                             TeamsRepository teamsRepository)
    {
        this.solutionsRepository = solutionsRepository;
        this.tasksRepository = tasksRepository;
        this.teamsRepository = teamsRepository;
    }

    @POST
    public Response submitSolution(@Auth User user,
                                   String hash) throws Exception
    {
        if (tasksRepository.checkHash(user, hash)) {
            return Response.ok().build();
        }
        return Response.status(Response.Status.NOT_ACCEPTABLE).build();
    }

    @GET
    @Path("/my")
    public Map<Integer, List<String>> getTeamSolutions(@Auth User user)
    {
        Optional<Team> team = teamsRepository.getTeamByUser(user);
        List<Solution> byTeam = solutionsRepository.getByTeam(team.get());
        Map<Task, List<Solution>> collect = byTeam.stream()
                .collect(Collectors.groupingBy(new Function<Solution, Task>()
                {
                    @Override
                    public Task apply(Solution solution)
                    {
                        return solution.getTask();
                    }
                }));

        Map<Integer, List<String>> collect1 = collect.entrySet().stream()
                .collect(Collectors.toMap(
                        taskSolutions -> taskSolutions.getKey().getLevel(),
                        taskSolutions -> taskSolutions.getValue().stream()
                                .map(solution -> solution.getFlag().getDescription()).collect(Collectors.toList())
                ));

        return collect1;
    }

    @GET
    @Path("/all")
    public Map<String, List<String>> getTeamsSolutions()
    {
        return solutionsRepository.getAll()
                .stream()
                .collect(Collectors.groupingBy(new Function<Solution, String>()
                {
                    @Override
                    public String apply(Solution solution)
                    {
                        return solution.getTask().getName();
                    }
                }))
                .entrySet()
                .stream()
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        entry -> entry.getValue().stream()
                                .map(solution -> solution.getTeam().getName())
                                .collect(Collectors.toList())
                ));

    }

}
