/*
 * 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.tallying.commons.io.writer;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.Security;
import java.util.ArrayList;
import java.util.List;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.asymmetric.service.AsymmetricService;
import com.scytl.cryptolib.primitives.service.PrimitivesService;
import com.scytl.products.oscore.logging.api.domain.Level;
import com.scytl.products.oscore.logging.api.domain.LogContent;
import com.scytl.products.oscore.logging.api.writer.LoggingWriter;
import com.scytl.products.oscore.logging.api.writer.SecureLoggingWriter;
import com.scytl.products.ov.commons.sign.MetadataFileSigner;
import com.scytl.products.ov.tallying.command.TallyingHolder;
import com.scytl.products.ov.tallying.commons.HashService;
import com.scytl.products.ov.tallying.commons.beans.TalliedInvalidVotes;
import com.scytl.products.ov.tallying.commons.exception.TallyingException;

import mockit.Mock;
import mockit.MockUp;

public class TalliedInvalidVotesWriterTest {

    private final TemporaryFolder _folder = new TemporaryFolder();

    @Rule
    public TemporaryFolder getFolder() {
        return _folder;
    }

    private static TalliedInvalidVotesWriter _target;

    @BeforeClass
    public static void setUp() throws GeneralCryptoLibException {
        Security.addProvider(new BouncyCastleProvider());

        _target = new TalliedInvalidVotesWriter(new SignResultWriter(new MetadataFileSigner(new AsymmetricService())),
            new HashService(new PrimitivesService()), new SecureLoggingWriter() {
                @Override
                public void log(LogContent content) {

                }

                @Override
                public void log(Level level, LogContent content, LoggingWriter loggingWriter) {

                }

                @Override
                public void log(Level level, LogContent logContent) {

                }
            });
    }

    @AfterClass
    public static void removeBouncyCastleProvider() {
        Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);
    }

    @Test
    public void write_to_file_correctly() throws TallyingException, IOException {

        new MockUp<SignResultWriter>() {
            @Mock
            public void signOutput(final Path originalFilePath, final TallyingHolder holder) {

            }
        };

        TalliedInvalidVotes talliedInvalidVotes = new TalliedInvalidVotes(3, 5);
        TallyingHolder holder = new TallyingHolder();
        holder.setOutputDir(Paths.get(getFolder().getRoot().getAbsolutePath()).resolve("tally"));
        holder.setInvalidVotesFileName("invalidVotes.csv");
        _target.writeToFiles(talliedInvalidVotes, holder);

        assertThat(getFolder().getRoot().listFiles().length, is(1));

        List<String> resultValues = parseOutputCSV(holder.getOutputDir().resolve("invalidVotes.csv").toFile());

        assertThat(resultValues.size(), is(3));

        assertThat(resultValues.get(0), is("5;cleansing_invalid_votes"));
        assertThat(resultValues.get(1), is("3;decryption_invalid_votes"));
        assertThat(resultValues.get(2), is("8;total_invalid_votes"));
    }

    private List<String> parseOutputCSV(File outputFile) throws IOException {

        List<String> results = new ArrayList<>();

        try (BufferedReader reader = new BufferedReader(new FileReader(outputFile))) {

            String currentLine;
            while ((currentLine = reader.readLine()) != null) {
                results.add(currentLine);
            }
        }

        return results;
    }
}
