/*
 * 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.commands.ballotbox;

import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.PrivateKey;

import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.io.FileUtils;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.certificates.cryptoapi.CryptoAPIX509Certificate;
import com.scytl.cryptolib.scytl.keystore.cryptoapi.CryptoAPIScytlKeyStore;
import com.scytl.products.oscore.logging.api.writer.LoggingWriter;
import com.scytl.products.ov.commons.beans.Ballot;
import com.scytl.products.ov.commons.beans.BallotBox;
import com.scytl.products.ov.commons.beans.EncryptionParameters;
import com.scytl.products.ov.config.commands.electionevent.datapacks.beans.ElectionCredentialDataPack;
import com.scytl.products.ov.config.commands.electionevent.datapacks.beans.ElectionInputDataPack;
import com.scytl.products.ov.config.commands.electionevent.datapacks.generators.ElectionCredentialDataPackGenerator;
import com.scytl.products.ov.constants.Constants;
import com.scytl.products.ov.datapacks.beans.CredentialProperties;
import com.scytl.products.ov.datapacks.helpers.ReplacementsHolder;
import com.scytl.products.ov.utils.ConfigObjectMapper;

import mockit.Deencapsulation;
import mockit.Expectations;
import mockit.Mocked;

public class BallotBoxGeneratorTest {

    private static BallotBoxGenerator _generator;

    private static String _bbIDa;

    private static String _ballotID;

    private static EncryptionParameters _encParams;

    private static Path _outputPath;

    private static Path _absoluteOnlinePath;

    private static Path _absoluteOfflinePath;

    private static Path _onlinePath1;

    private static Path _offlinePath1;

    @BeforeClass
    public static void setUp() throws IOException {

        _bbIDa = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";

        _ballotID = "cccccccccccccccccccccccccccccccc";

        _encParams = new EncryptionParameters();
        _encParams.setP("23");
        _encParams.setQ("11");
        _encParams.setG("2");

        _outputPath = Files.createTempDirectory("outputPath");

        _absoluteOnlinePath =
            Paths.get(_outputPath.toString(), Constants.ONLINE_DIRECTORY, Constants.ELECTION_INFORMATION_DIRECTORY,
                Constants.BALLOTS_DIRECTORY, _ballotID, Constants.BALLOT_BOXES_DIRECTORY).toAbsolutePath();

        _absoluteOfflinePath =
            Paths.get(_outputPath.toString(), Constants.OFFLINE_DIRECTORY, Constants.ELECTION_INFORMATION_DIRECTORY,
                Constants.BALLOTS_DIRECTORY, _ballotID, Constants.BALLOT_BOXES_DIRECTORY).toAbsolutePath();

        _onlinePath1 = Paths.get(_absoluteOnlinePath.toString(), _bbIDa);
        Files.createDirectories(_onlinePath1);

        _offlinePath1 = Paths.get(_absoluteOfflinePath.toString(), _bbIDa);
        Files.createDirectories(_offlinePath1);

        Path ballotFilePath = Paths.get(_outputPath.toString(), Constants.ONLINE_DIRECTORY,
            Constants.ELECTION_INFORMATION_DIRECTORY, Constants.BALLOTS_DIRECTORY, _ballotID, "ballot.json");

        Files.createFile(ballotFilePath);
    }

    @AfterClass
    public static void tearDown() throws IOException {

        FileUtils.deleteDirectory(_outputPath.toFile());
    }

    @Test
    public void generate_a_valid_ballot_box(
            @Mocked final ElectionCredentialDataPackGenerator electionCredentialDataPackGenerator,
            @Mocked final BallotBoxParametersHolder ballotBoxParametersHolder,
            @Mocked final CryptoAPIX509Certificate servicesCACert,
            @Mocked final CryptoAPIX509Certificate electionCACert,
            @Mocked final CredentialProperties ballotBoxCredentialProperties,
            @Mocked final ElectionInputDataPack electionInputDataPack, @Mocked final PrivateKey privateKey,
            @Mocked final CryptoAPIScytlKeyStore systemCAKeyStore, @Mocked final ElectionCredentialDataPack dataPack,
            @Mocked final Files files, @Mocked final BallotBox ballotBox, @Mocked final Ballot ballot,
            @Mocked final ConfigObjectMapper mapper, @Mocked final CryptoAPIScytlKeyStore ballotBoxKeystore,
            @Mocked final ReplacementsHolder replacementsHolder, @Mocked final LoggingWriter logWriter)
            throws ConfigurationException, IOException, GeneralCryptoLibException, URISyntaxException {

        _generator = new BallotBoxGenerator(electionCredentialDataPackGenerator);

        Deencapsulation.setField(_generator, logWriter);

        new Expectations() {
            {
                ballotBoxParametersHolder.getBallotBoxID();
                result = _bbIDa;
                times = 1;

                ballotBoxParametersHolder.getBallotID();
                result = _ballotID;
                times = 1;

                ballot.getId();
                result = _ballotID;
                times = 1;

                ballotBoxParametersHolder.getOutputPath();
                result = _outputPath;
                times = 1;

                ballotBoxParametersHolder.getBallotID();
                result = _ballotID;
                times = 1;

                ballotBoxParametersHolder.getEncryptionParameters();
                result = _encParams;
                times = 1;

                ballotBoxParametersHolder.getServicesCACert();
                result = servicesCACert;
                times = 1;

                ballotBoxParametersHolder.getElectionCACert();
                result = electionCACert;
                times = 1;

                ballotBoxParametersHolder.getBallotBoxCredentialProperties();
                result = ballotBoxCredentialProperties;
                times = 1;

                ballotBoxParametersHolder.getInputDataPack();
                result = electionInputDataPack;
                times = 1;

                electionInputDataPack.setCredentialProperties(ballotBoxCredentialProperties);
                result = null;
                times = 1;

                ballotBoxParametersHolder.getSignerPrivateKey();
                result = privateKey;
                times = 1;

                dataPack.getPassword();
                result = "keystorePassword".toCharArray();
                times = 1;

                dataPack.getEncryptedPassword();
                result = "encryptedKeystorePassword";
                times = 1;

                dataPack.getKeyStore();
                result = ballotBoxKeystore;
                times = 1;

                ballotBoxKeystore.toJSON("keystorePassword".toCharArray());
                result = "mockedKeystoreString";
                times = 1;

            }
        };

        _generator.generate(ballotBoxParametersHolder);
    }
}
