package repositories;

import core.ApplicationConfiguration;
import database.MongoDBConnector;
import objects.Solution;
import objects.Task;
import org.apache.commons.codec.binary.Hex;
import org.bson.Document;

import javax.inject.Inject;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by gpietrus on 20.02.2016.
 */
public class TasksRepository implements Repository {

    private ApplicationConfiguration applicationConfiguration;
    private MongoDBConnector mongoDBConnector;
    private TeamsRepository teamsRepository;
    private SolutionsRepository solutionsRepository;
    private String salt = "SECURE_SALT"; //todo

    @Inject
    public TasksRepository(ApplicationConfiguration applicationConfiguration, MongoDBConnector mongoDBConnector,
                           TeamsRepository teamsRepository, SolutionsRepository solutionsRepository) {
        this.applicationConfiguration = applicationConfiguration;
        this.mongoDBConnector = mongoDBConnector;
        this.teamsRepository = teamsRepository;
        this.solutionsRepository = solutionsRepository;
    }

    public void get(UUID uuid) {

    }

    public List<Task> getAll() {
        return mongoDBConnector.getCollection("tasks")
                .stream()
                .map(Task::new)
                .collect(Collectors.toList());
    }

    public void add(Task task) {
        mongoDBConnector.addDocument("tasks", new Document(task.toMap()));
    }

    public void clean() {
        mongoDBConnector.removeCollection("tasks");
    }

    public Map<String, Task> getUserFlagsHashes(String username) {
        return this.getAll().stream()
                .collect(Collectors.toMap(
                        task -> calculateHashValue(username, task.getFlag().getValue()),
                        task -> task
                ));
    }

    public String calculateHashValue(String username, String flagValue) { //todo
        String combinedStrings = salt + username + flagValue; //todo
        MessageDigest md5 = null;//todo: discuss
        try {
            md5 = MessageDigest.getInstance(applicationConfiguration.getFlagHashMethod());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        String encodedHash = Hex.encodeHexString(md5.digest(combinedStrings.getBytes()));
        return encodedHash;
    }

    private void acceptSolution(String username, Task task) {
        //todo: getname, of get id?
        solutionsRepository.add(new Solution(teamsRepository.getTeamByUser(username).getName(), task.getName()));
    }

    private boolean compareHash(String hash, String username) throws Exception {
        Task task = getUserFlagsHashes(username).get(hash);

        if (task != null) {
            acceptSolution(username, task);
            return true;
        }
        return false;
    }

    public boolean checkFlag(String username, String flagValue) throws Exception {
        return compareHash(flagValue, username);
    }
}

//todo: generify!