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

import com.scytl.products.ov.commons.verify.CryptolibPayloadSigningCertificateValidator;
import com.scytl.products.ov.commons.verify.PayloadSigningCertificateValidator;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;

import com.scytl.cryptolib.api.asymmetric.AsymmetricServiceAPI;
import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.api.primitives.PrimitivesServiceAPI;
import com.scytl.cryptolib.api.services.ServiceFactory;
import com.scytl.cryptolib.asymmetric.service.AsymmetricServiceFactoryHelper;
import com.scytl.products.oscore.logging.api.writer.SecureLoggingWriter;
import com.scytl.products.oscore.logging.core.provider.TransactionInfoProvider;
import com.scytl.products.ov.commons.sign.MetadataFileSigner;
import com.scytl.products.ov.commons.util.ConfigObjectMapper;
import com.scytl.products.ov.commons.verify.CryptolibPayloadVerifier;
import com.scytl.products.ov.commons.verify.PayloadVerifier;
import com.scytl.products.ov.mixnet.spring.MixerSpringConfig;
import com.scytl.products.ov.validation.ValidationController;
import com.scytl.products.ov.validation.decompress.GroupElementDecompressor;
import com.scytl.products.ov.validation.decompress.VoteValidator;
import com.scytl.products.ov.validation.services.ValidationService;
import com.scytl.products.ov.validation.services.ValidationServiceImpl;
import com.scytl.products.ov.validation.services.input.VoteWithProofEntryParser;
import com.scytl.products.ov.validation.services.input.VotesWithProofReader;

@PropertySource("classpath:springConfig.properties")
public class MixDecValSpringConfig extends MixerSpringConfig {

    @Autowired
    private Environment env;

    @Bean
    private ValidationController validationController(ValidationService validationService)
            throws GeneralCryptoLibException {
        return new ValidationController(validationService);
    }

    @Bean
    private ValidationService validationService(VotesWithProofReader votesWithProofReader,
            GroupElementDecompressor groupElementDecompressor, VoteValidator voteValidator,
            PrimitivesServiceAPI primitivesService, SecureLoggingWriter secureLoggingWriter,
            TransactionInfoProvider transactionInfoProvider, MetadataFileSigner metadataFileSigner) {
        return new ValidationServiceImpl(votesWithProofReader, groupElementDecompressor, voteValidator,
            primitivesService, secureLoggingWriter, transactionInfoProvider, metadataFileSigner);
    }

    @Bean
    private VoteValidator voteValidator() {
        return new VoteValidator();
    }

    @Bean
    private MetadataFileSigner metadataFileSigner(AsymmetricServiceAPI asymmetricService) {
        return new MetadataFileSigner(asymmetricService);
    }

    @Bean
    public GenericObjectPoolConfig genericObjectPoolConfig() {

        GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig();
        genericObjectPoolConfig.setMaxTotal(Integer.valueOf(env.getProperty("services.cryptolib.pool.size")));
        genericObjectPoolConfig.setMaxIdle(Integer.valueOf(env.getProperty("services.cryptolib.timeout")));

        return genericObjectPoolConfig;
    }

    @Bean
    public ServiceFactory<AsymmetricServiceAPI> asymmetricServiceAPIServiceFactory(
            final GenericObjectPoolConfig genericObjectPoolConfig) {
        return AsymmetricServiceFactoryHelper.getFactoryOfThreadSafeServices(genericObjectPoolConfig);
    }

    @Bean
    public AsymmetricServiceAPI asymmetricService(final ServiceFactory<AsymmetricServiceAPI> asymmetricServiceFactory)
            throws GeneralCryptoLibException {
        return asymmetricServiceFactory.create();
    }

    @Bean
    private GroupElementDecompressor groupElementDecompressor() {
        return new GroupElementDecompressor();
    }

    @Bean
    private VotesWithProofReader votesWithProofReader(VoteWithProofEntryParser entryParser,
            SecureLoggingWriter secureLoggingWriter) {
        return new VotesWithProofReader(entryParser, secureLoggingWriter);
    }

    @Bean
    private VoteWithProofEntryParser getEntryParser() {
        return new VoteWithProofEntryParser(objectMapper());
    }

    @Bean
    private ConfigObjectMapper objectMapper() {
        return new ConfigObjectMapper();
    }

    @Bean
    private PayloadVerifier payloadVerifier(AsymmetricServiceAPI asymmetricService,
            PayloadSigningCertificateValidator certificateValidator) {
        return new CryptolibPayloadVerifier(asymmetricService, certificateValidator);
    }

    @Bean
    private PayloadSigningCertificateValidator certificateValidator() {
        return new CryptolibPayloadSigningCertificateValidator();
    }
}
