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

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;

import com.googlecode.jcsv.reader.CSVReader;
import com.googlecode.jcsv.reader.internal.CSVReaderBuilder;
import com.scytl.cryptolib.elgamal.cryptoapi.Ciphertext;
import com.scytl.cryptolib.mathematical.groups.impl.ZpSubgroup;
import com.scytl.products.ov.mixnet.commons.ballots.ElGamalEncryptedBallots;
import com.scytl.products.ov.mixnet.commons.exceptions.InvalidInputException;
import com.scytl.products.ov.mixnet.commons.validation.EncryptedBallotsValidator;
import com.scytl.products.ov.mixnet.commons.validation.ValidationResult;

/**
 * Loads an {@code ElGamalEncryptedBallots} from a source.
 */
public final class ElGamalEncryptedBallotsLoader {

    private final EncryptedBallotsValidator validator;

    /**
     * Create an ElGamalEncryptedBallotsLoader, including the initialization of the validators that will be used while
     * loading data. The following validators are initialized:
     * <ul>
     * <li>{@code EncryptedBallotsDuplicationValidator}</li>
     * </ul>
     */
    public ElGamalEncryptedBallotsLoader(final EncryptedBallotsValidator validator) {

        this.validator = validator;

    }

    public ElGamalEncryptedBallots loadCSV(final ZpSubgroup zpGroup, final InputStream inputstream) throws IOException {

        ElGamalEncryptedBallotEntryParser entryParser = new ElGamalEncryptedBallotEntryParser(zpGroup);

        final ElGamalEncryptedBallots elGamalEncryptedBallots;

        try (Reader reader = new InputStreamReader(inputstream);
                CSVReader<Ciphertext> elGamalEncryptedBallotReader =
                    new CSVReaderBuilder<Ciphertext>(reader).entryParser(entryParser).build()) {

            elGamalEncryptedBallots = new ElGamalEncryptedBallots(elGamalEncryptedBallotReader.readAll());
        }

        final ValidationResult validation = validator.validate(elGamalEncryptedBallots);

        if (!validation.getResult()) {
            throw new InvalidInputException(validation.getInfo());
        }

        return elGamalEncryptedBallots;
    }
}
