/*
 * 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.sdm.config.spring.batch.writers;

import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.nio.file.Files;
import java.nio.file.Path;
import java.security.Security;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.batch.item.ExecutionContext;

import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.primitives.service.PrimitivesService;
import com.scytl.products.oscore.logging.api.writer.LoggingWriter;
import com.scytl.products.ov.config.commands.voters.datapacks.beans.VotingCardCredentialDataPack;
import com.scytl.products.ov.sdm.config.spring.batch.GeneratedVotingCardOutput;
import com.scytl.products.ov.utils.FingerprintGenerator;

@RunWith(MockitoJUnitRunner.class)
public class CredentialDataWriterTest {

    @Rule
    public TemporaryFolder tempFolder = new TemporaryFolder();

    private String keyStoreJson;

    @BeforeClass
    public static void setup() {
        Security.addProvider(new BouncyCastleProvider());
    }

    // cant mock final class
    private FingerprintGenerator fingerprintGenerator;

    @Before
    public void setupKeystore() throws GeneralCryptoLibException {
        keyStoreJson = "Key store JSON";

        fingerprintGenerator = new FingerprintGenerator(new PrimitivesService());
    }

    @Mock
    private LoggingWriter mockLoggingWriter;

    // this is to document what the exact format we are expecting the writer writes
    private int expectedFormatLength = "%s,%s".split(",").length;

    @Test
    public void generateOutputFileWithCorrectDataFormat() throws Exception {

        doNothing().when(mockLoggingWriter).log(any(), any());

        Path tempPath = tempFolder.newFile().toPath();

        CredentialDataWriter sut = new CredentialDataWriter(tempPath, fingerprintGenerator, mockLoggingWriter);
        sut.open(new ExecutionContext(Collections.emptyMap()));

        final String credentialId = "credentialId";
        List<GeneratedVotingCardOutput> items = new ArrayList<>();
        items.add(createOutput(credentialId));
        items.add(createOutput(credentialId));
        items.add(createOutput(credentialId));

        sut.write(items);

        final List<String> strings = Files.readAllLines(tempPath);
        Assert.assertEquals(items.size(), strings.size());

        strings.forEach((String l) -> {
            final String[] columns = l.split(",");

            Assert.assertEquals(expectedFormatLength, columns.length);
            Assert.assertEquals(credentialId, columns[0]);
            String decodedKeyStore = columns[1];
            Assert.assertEquals(keyStoreJson, decodedKeyStore);
        });
    }

    private GeneratedVotingCardOutput createOutput(String credentialId) {

        VotingCardCredentialDataPack votingCardCredentialDataPack = mock(VotingCardCredentialDataPack.class);
        when(votingCardCredentialDataPack.getSerializedKeyStore()).thenReturn(keyStoreJson);

        return GeneratedVotingCardOutput.success(null, null, null, null, credentialId, null, null, null, null,
            votingCardCredentialDataPack, null, null, null);
    }

}
