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

import static java.nio.file.Files.newDirectoryStream;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.DirectoryStream;
import java.nio.file.DirectoryStream.Filter;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import com.scytl.products.ov.constants.Constants;

public class  VotersSerializationDestProvider {

    private final Path voterMaterialOnlinePath;

    private final Path voteVerificationOnlinePath;

    private final Path printingOnlinePath;

    private final Path customFolderPath;

    private final Path extendedAuthenticationPath;

    public VotersSerializationDestProvider(final Path voterMaterialOnlinePath, final Path voteVerificationOnlinePath,
            final Path printingOnlinePath, final Path customFolderPath, final Path extendedAuthenticationPath) {
        this.voterMaterialOnlinePath = voterMaterialOnlinePath;
        this.voteVerificationOnlinePath = voteVerificationOnlinePath;
        this.printingOnlinePath = printingOnlinePath;
        this.customFolderPath = customFolderPath;
        this.extendedAuthenticationPath = extendedAuthenticationPath;
    }

    public Path getTempVoterInformation(final String version) {
        return Paths.get(voterMaterialOnlinePath.toString(),
            Constants.VOTER_INFORMATION_FILENAME + version + Constants.CSV);
    }

    public Path getTempCredentialsData(final String version) {
        return Paths.get(voterMaterialOnlinePath.toString(),
            Constants.CREDENTIAL_DATA_FILENAME + version + Constants.CSV);
    }

    public Path getTempVerificationCardSetData(final String version) {
        return Paths.get(voteVerificationOnlinePath.toString(),
            Constants.VERIFICATION_CARD_SET_DATA + version + Constants.JSON);
    }

    public Path getTempVerificationCardIds(final String version) {
        return Paths.get(voteVerificationOnlinePath.toString(),
                Constants.VERIFICATION_CARD_IDS + version + Constants.CSV);
    }

    public Path getTempVoteVerificationContextData(final String version) {
        return Paths.get(voteVerificationOnlinePath.toString(),
            Constants.VOTE_VERIFICATION_CONTEXT_DATA + version + Constants.JSON);
    }

    public Path getTempVerificationCardData(final String version) {
        return Paths.get(voteVerificationOnlinePath.toString(),
            Constants.VERIFICATION_CARD_DATA + version + Constants.CSV);
    }

    public Path getTempCodesMappingTablesContextData(final String version) {
        return Paths.get(voteVerificationOnlinePath.toString(),
            Constants.CODES_MAPPING_TABLES_CONTEXT_DATA + version + Constants.CSV);
    }

    public Path getTempComputedValues(final String version) {
        return Paths.get(voteVerificationOnlinePath.toString(),
            Constants.COMPUTED_VALUES_FILENAME + version + Constants.CSV);
    }
    
    public List<Path> getTempNodeContributions() {
        List<Path> files = new LinkedList<>();
        // we cannot just compose a path because the returned list depends on the number of chunks
        Filter<Path> filter = VotersSerializationDestProvider::isNodeContributions;
        try (DirectoryStream<Path> stream = newDirectoryStream(voteVerificationOnlinePath, filter)) {
            stream.forEach(files::add);
        } catch (IOException e) {
            // I/O error here means either programming error when the operation is called at wrong time
            // or damaged file structure, which is not recoverable, in both cases the exception cannot 
            // be handled.
            throw new UncheckedIOException(e);
        }
        return files;
    }
    
    private static boolean isNodeContributions(Path file) {
        String name = file.getFileName().toString();
        return name.startsWith(Constants.NODE_CONTRIBUTIONS_FILENAME)
                && name.endsWith(Constants.JSON);
    }
    
    public Path getTempDerivedKeys(final String version) {
        return Paths.get(voteVerificationOnlinePath.toString(),
            Constants.DERIVED_KEYS_FILENAME + version + Constants.CSV);
    }

    public Path getTempPrintingData(final String version) {
        return Paths.get(printingOnlinePath.toString(), Constants.PRINTING_DATA + version + Constants.CSV);
    }

    public Path getTempNumicOtlFileName(final String version) {
        return Paths.get(customFolderPath.toAbsolutePath().toString(),
            Constants.NUMIC_OTL_MAPPING_FILENAME + version + Constants.CSV);
    }

    public Path getTempIdMapping(final String version) {
        return Paths.get(customFolderPath.toAbsolutePath().toString(),
            Constants.ID_MAPPING_FILENAME + version + Constants.CSV);
    }

    public Path getTempSmsProvider(final String version) {
        return Paths.get(customFolderPath.toAbsolutePath().toString(),
            Constants.SMS_PROVIDER_FILENAME + version + Constants.CSV);
    }

    public Path getTempCredRecovery(final String version) {
        return Paths.get(customFolderPath.toAbsolutePath().toString(),
            Constants.CRED_RECOVERY_FILENAME + version + Constants.CSV);
    }

    public Path getTempCredUpdate(final String version) {
        return Paths.get(customFolderPath.toAbsolutePath().toString(),
            Constants.CRED_UPDATE_FILENAME + version + Constants.CSV);
    }

    public Path getTempSecrets(final String version, final String secretName) {
        return Paths.get(printingOnlinePath.toString(), secretName + version + Constants.OUT);
    }

    public Path getTempExtendedAuth(final String version) {
        return Paths.get(extendedAuthenticationPath.toString(),
            Constants.EXTENDED_AUTHENTICATION + version + Constants.CSV);
    }

    public Path getProvidedChallenge(final String version) {
        return Paths.get(printingOnlinePath.toString(), Constants.PROVIDED_CHALLENGE + version + Constants.CSV);
    }

    public Path getVoterInformation() {
        return getTempVoterInformation(Constants.EMPTY);
    }

    public Path getCredentialsData() {
        return getTempCredentialsData(Constants.EMPTY);
    }

    public Path getVerificationCardSetData() {
        return getTempVerificationCardSetData(Constants.EMPTY);
    }

    public Path getVerificationCardIds(){
        return getTempVerificationCardIds(Constants.EMPTY);
    }

    public Path getVoteVerificationContextData() {
        return getTempVoteVerificationContextData(Constants.EMPTY);
    }

    public Path getVerificationCardData() {
        return getTempVerificationCardData(Constants.EMPTY);
    }

    public Path getCodesMappingTablesContextData() {
        return getTempCodesMappingTablesContextData(Constants.EMPTY);
    }

    public Path getComputedValues() {
        return getTempComputedValues(Constants.EMPTY);
    }
    
    public List<Path> getNodeContributions() {
        return getTempNodeContributions();
    }
    
    public Path getDerivedKeys() {
        return getTempDerivedKeys(Constants.EMPTY);
    }

    public Path getPrintingData() {
        return getTempPrintingData(Constants.EMPTY);
    }

    public Path getExtendedAuthentication() {
        return getTempExtendedAuth(Constants.EMPTY);
    }

    public Path getProvidedChallenge() {
        return getProvidedChallenge(Constants.EMPTY);
    }

    public Path getIdMapping() {
        return getTempIdMapping(Constants.EMPTY);
    }

    public List<Path> listOutputPaths() {
        final List<Path> outputPaths = new ArrayList<>();
        outputPaths.add(voterMaterialOnlinePath);
        outputPaths.add(voteVerificationOnlinePath);
        outputPaths.add(printingOnlinePath);
        return outputPaths;
    }
}
