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

import java.security.Security;
import java.util.UUID;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Profile;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.PropertySources;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import com.scytl.cryptolib.api.asymmetric.AsymmetricServiceAPI;
import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.asymmetric.service.AsymmetricService;
import com.scytl.products.oscore.logging.api.domain.TransactionInfo;
import com.scytl.products.oscore.logging.api.factory.LoggingFactory;
import com.scytl.products.oscore.logging.core.factory.LoggingFactoryLog4j;
import com.scytl.products.oscore.logging.core.formatter.SplunkFormatter;
import com.scytl.products.oscore.logging.core.provider.TransactionInfoProvider;
import com.scytl.products.ov.commons.path.PathResolver;
import com.scytl.products.ov.commons.path.PrefixPathResolver;
import com.scytl.products.ov.commons.sign.MetadataFileSigner;
import com.scytl.products.ov.commons.verify.MetadataFileVerifier;
import com.scytl.products.ov.sdm.application.config.SecureLoggingConfig;
import com.scytl.products.ov.sdm.application.service.HashService;
import com.scytl.products.ov.sdm.application.service.KeyStoreService;
import com.scytl.products.ov.sdm.application.service.KeyStoreServiceForTesting;
import com.scytl.products.ov.sdm.domain.service.utils.PublicKeyLoader;
import com.scytl.products.ov.sdm.domain.service.utils.SystemTenantPublicKeyLoader;
import com.scytl.products.ov.sdm.infrastructure.DatabaseManager;
import com.scytl.products.ov.sdm.infrastructure.DatabaseManagerFactory;

/**
 * MVC Configuration
 */
@Configuration
@ComponentScan(basePackages = {"com.scytl.products.ov.sdm.infrastructure" })
@PropertySources({@PropertySource("classpath:config/application.properties"),
        @PropertySource("${upload.config.source}"), @PropertySource("${download.config.source}"),
        @PropertySource("${sdm.config.source}"), @PropertySource("${adapter.properties}") })
@Profile("test")
@Import({SecureLoggingConfig.class})
public class ConfigTest {
    @Value("${user.home}")
    private String prefix;

    @Autowired
    private DatabaseManagerFactory databaseManagerFactory;

    public ConfigTest() {
        Security.addProvider(new BouncyCastleProvider());
    }

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertiesResolver() {
        return new PropertySourcesPlaceholderConfigurer();
    }

    @Bean
    public PathResolver getPrefixPathResolver() {
        return new PrefixPathResolver(prefix);
    }

    @Bean
    public ObjectMapper objectMapper() {
        return new ObjectMapper();
    }

    @Bean
    public SystemTenantPublicKeyLoader getSystemTenantPublicKeyLoader() {
        return new SystemTenantPublicKeyLoader();
    }

    @Bean
    public PublicKeyLoader getPublicKeyLoader() {
        return new PublicKeyLoader();
    }

    @Bean
    public MetadataFileVerifier getMetadataFileVerifier(final AsymmetricServiceAPI asymmetricServiceAPI) {
        return new MetadataFileVerifier(asymmetricServiceAPI);
    }

    @Bean
    public MetadataFileSigner getMetadataFileSigner(final AsymmetricServiceAPI asymmetricServiceAPI) {
        return new MetadataFileSigner(asymmetricServiceAPI);
    }

    @Bean
    AsymmetricServiceAPI asymmetricServiceAPI() throws GeneralCryptoLibException {
        return new AsymmetricService();
    }

    @Bean
    LoggingFactory loggingFactory() {
        return new LoggingFactoryLog4j(new SplunkFormatter("OV", "SDM", getTransactionInfoProvider()));
    }

    @Bean
    TransactionInfoProvider getTransactionInfoProvider() {
        TransactionInfoProvider provider = new TransactionInfoProvider();
        TransactionInfoProvider spy = Mockito.spy(provider);
        Mockito.when(spy.get()).thenReturn(new TransactionInfo(-1L, "", "", ""));
        return spy;
    }

    @Bean(initMethod = "createDatabase")
    DatabaseManager databaseManager() {
        String url = "memory:" + UUID.randomUUID();
        return databaseManagerFactory.newDatabaseManager(url);
    }

    @Bean
    KeyStoreService getKeyStoreService() {
        return new KeyStoreServiceForTesting();
    }

    @Bean
    HashService getHashService() throws GeneralCryptoLibException {
        return new HashService();
    }

    @Bean
    ObjectReader jsonReader() { 
        return new ObjectMapper().reader();
    }
}
