/*
 * Copyright 2018 Scytl Secure Electronic Voting SA
 *
 * All rights reserved
 *
 * See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package
 */
package com.scytl.products.ov.config.it.verifiers;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.lang3.StringUtils;
import org.junit.Assert;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.scytl.products.ov.commons.beans.BallotBox;
import com.scytl.products.ov.commons.beans.VoteVerificationContextData;
import com.scytl.products.ov.constants.Constants;
import com.scytl.products.ov.utils.ConfigObjectMapper;
import com.scytl.products.ov.utils.IDsParser;

/**
 * A class to execute all validations related with Create Electoral Board Key
 * command
 */
public class CreateEBKeyVerifier {

    private final ConfigObjectMapper _mapper = new ConfigObjectMapper();

    private final IDsParser _idsParser = new IDsParser();

    /**
     * @param ebPropertiesPath
     * @throws IOException
     */
    public void createEBKeyPairValidations(final File eeidFolder, final Path ebPropertiesPath, String vcsids)
            throws IOException {

        offlineFolderValidations(eeidFolder, ebPropertiesPath);

        onlineFolderValidations(eeidFolder, ebPropertiesPath, vcsids);
    }

    /**
     * @param eeidFolder
     * @param ebPropertiesPath
     * @throws IOException
     */
    private void offlineFolderValidations(final File eeidFolder, final Path ebPropertiesPath) throws IOException {

        final Map<String, List<String>> ballotMappings = getBallotMappings(ebPropertiesPath);

        for (final String ballotId : ballotMappings.keySet()) {

            for (final String ballotBoxID : ballotMappings.get(ballotId)) {

                final Path ballotIdPath = Paths.get(eeidFolder.getAbsolutePath(), Constants.OFFLINE_DIRECTORY,
                    Constants.ELECTION_INFORMATION_DIRECTORY, Constants.BALLOTS_DIRECTORY, ballotId,
                    Constants.BALLOT_BOXES_DIRECTORY, ballotBoxID);

                final Path ebPrivateKeyPath = Paths.get(ballotIdPath.toString(), Constants.EB_PRIVATE_KEY_FILENAME);
                Assert.assertTrue(Files.exists(ebPrivateKeyPath));
            }
        }
    }

    /**
     * @param eeidFolder
     * @param ebPropertiesPath
     * @throws IOException
     * @throws JsonParseException
     * @throws JsonMappingException
     */
    private void onlineFolderValidations(final File eeidFolder, final Path ebPropertiesPath, String vcsids)
            throws IOException {

        Map<String, List<String>> ballotMappings = getBallotMappings(ebPropertiesPath);
        for (String ballotId : ballotMappings.keySet()) {

            Path ballotsBoxesFolder = Paths.get(eeidFolder.getAbsolutePath(), Constants.ONLINE_DIRECTORY,
                Constants.ELECTION_INFORMATION_DIRECTORY, Constants.BALLOTS_DIRECTORY, ballotId,
                Constants.BALLOT_BOXES_DIRECTORY);

            for (String ballotBoxId : ballotMappings.get(ballotId)) {

                Path ballotBoxIdFolder = Paths.get(ballotsBoxesFolder.toString(), ballotBoxId);
                Path ballotBoxJSONPath = Paths.get(ballotBoxIdFolder.toString(), Constants.BALLOT_BOX_FILENAME);

                BallotBox ballotBox = _mapper.fromJSONFileToJava(ballotBoxJSONPath.toFile(), BallotBox.class);
                Assert.assertTrue(StringUtils.isNotEmpty(ballotBox.getElectoralAuthorityId()));
            }
        }

        for (String vcsid : _idsParser.parse(vcsids)) {
            Path voteVerificationContextDataPath = Paths.get(eeidFolder.getAbsolutePath(), Constants.ONLINE_DIRECTORY,
                Constants.VOTE_VERIFICATION_DIRECTORY, vcsid,
                Constants.VOTE_VERIFICATION_CONTEXT_DATA + Constants.JSON);
            Assert.assertTrue(Files.exists(voteVerificationContextDataPath));

            VoteVerificationContextData voteVerificationContextData =
                _mapper.fromJSONFileToJava(voteVerificationContextDataPath.toFile(), VoteVerificationContextData.class);
            Assert.assertTrue(StringUtils.isNotEmpty(voteVerificationContextData.getElectoralAuthorityId()));
        }
    }

    /**
     * @throws IOException
     */
    private Map<String, List<String>> getBallotMappings(final Path ebPropertiesPath) throws IOException {
        Properties props = new Properties();
        try (BufferedReader bufferedReader = Files.newBufferedReader(ebPropertiesPath)) {
            props.load(bufferedReader);
        }

        Map<String, List<String>> ballotMappings = new HashMap<>();
        for (String key : props.stringPropertyNames()) {

            String values = props.getProperty(key);
            String[] ballotBoxesIds = values.split(",");

            ballotMappings.put(key, Arrays.asList(ballotBoxesIds));
        }

        return ballotMappings;
    }

}
