/*
 * 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.ea.ui.ws.rs.application.operation;

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

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.Security;

import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

import org.apache.commons.io.FileUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.certificates.configuration.X509CertificateValidationResult;
import com.scytl.cryptolib.certificates.configuration.X509CertificateValidationType;
import com.scytl.products.ov.commons.beans.domain.model.platform.PlatformInstallationData;
import com.scytl.products.ov.commons.beans.exceptions.DuplicateEntryException;
import com.scytl.products.ov.commons.beans.validation.CertificateValidationService;
import com.scytl.products.ov.commons.beans.validation.CryptographicOperationException;
import com.scytl.products.ov.commons.domain.model.platform.PlatformCARepository;
import com.scytl.products.ov.commons.logging.domain.model.LoggingKeystoreRepository;
import com.scytl.products.ov.ea.services.infrastructure.logging.EaLoggingInitializationState;

public class EaPlatformDataResourceTest {
    private String platform = "-----BEGIN CERTIFICATE-----"
            + "MIIDYjCCAkqgAwIBAgIVAK1iv49QAkCz0vpq/cfHtrFdPv9BMA0GCSqGSIb3DQEB"
            + "CwUAMFgxFjAUBgNVBAMMDVNjeXRsIFJvb3QgQ0ExFjAUBgNVBAsMDU9ubGluZSBW"
            + "b3RpbmcxDjAMBgNVBAoMBVNjeXRsMQkwBwYDVQQHDAAxCzAJBgNVBAYTAkVTMB4X"
            + "DTE2MTAyMDAwMDAwMFoXDTE4MTAyMDIzMDAwMFowWDEWMBQGA1UEAwwNU2N5dGwg"
            + "Um9vdCBDQTEWMBQGA1UECwwNT25saW5lIFZvdGluZzEOMAwGA1UECgwFU2N5dGwx"
            + "CTAHBgNVBAcMADELMAkGA1UEBhMCRVMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw"
            + "ggEKAoIBAQDKit/euH0XFMSot/CEDW9MN0Uoxxo6lKFb6gtyraQUoS1hSawXTRyr"
            + "sMzjEbnZQY1lPWgFAZCMzSVK7RZVetiqng3uTmWFll5/XtyxR+P4GD0Q6OW0icFr"
            + "oDAQ4AD/YMEVX7T/dWsnh1j/NIg1sXsTLjNZyswXiXlhe71wrEFb61/NtxFu//rn"
            + "ZtPL/oQn/MLmXtrQZVPEQ1KDhPpAbvruNyqkThWyNvoEf3pUMeYuwMwNqcgPiOj3"
            + "1z9orIeMCnTagquJc3KbEE2/WFPaWmETl4w+gpUcafxmFvsSXijvmaMW86sc+GT2"
            + "L5NjFpewSXG0vghg7f167tC9uIZBQ2rhAgMBAAGjIzAhMA8GA1UdEwEB/wQFMAMB"
            + "Af8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4IBAQAEU1EcIPEUQOf8"
            + "Do0Z+R3JwRo6YmknCbATSDNmjGHLLwsaJn0SnI+fQXLdw1eE8XR3WnmF2Oi0ZDO+"
            + "6wFo+cZYFHtaCoO4TqpJjyJt9lDXOGv0+tTkmHRZdGfceVhbg1aX3tEL5a3Nkyt5"
            + "dolPZmtMqLVUsxOQOU+/q6S9cRaSeSukEc/xgydeOAJ3LBrAGCGUXMNxqf/g7u8n"
            + "jQ3QEOydTxfZh7UKndufnFSzP8RlPYAJsoknwmsl/SgSCNcaGNJoTBAUKw30xATe"
            + "NzP7MQZ+wvdix18dshSyCemV5cdTNT4ZpEh8DUuc80KrCKOIHSeydpUUe2Khvdb8" + "cD7sazdu" + "-----END CERTIFICATE-----";

    private final String loggingPasswordsFileName = "logging_EA.properties";

    private static final String ENCRYPTION_KEYSTORE_BASE64 =
        "[encoded data, 4888 characters]";

    private static final String SIGNING_KEYSTORE_BASE64 =
        "[encoded data, 4868 characters]";

    private EaPlatformDataResource resource;

    @BeforeClass
    public static void init(){
        if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
            Security.addProvider(new BouncyCastleProvider());
        }
    }
    
    @Before
    public void setUp() {
        resource = new EaPlatformDataResource();
        resource.certificateValidationService = mock(CertificateValidationService.class);
        resource.platformRepository = mock(PlatformCARepository.class);
        resource.loggingKeystoreRepository = mock(LoggingKeystoreRepository.class);
        resource.loggingInitializationState = mock(EaLoggingInitializationState.class);
    }

    @Test
    public void testSuccessfulResponse() throws DuplicateEntryException, GeneralCryptoLibException, 
        CryptographicOperationException, URISyntaxException, IOException {
        prepareEnvironment();
        
        PlatformInstallationData data = new PlatformInstallationData();
        data.setLoggingEncryptionKeystoreBase64(ENCRYPTION_KEYSTORE_BASE64);
        data.setLoggingSigningKeystoreBase64(SIGNING_KEYSTORE_BASE64);
        data.setPlatformRootCaPEM(platform);
        data.setPlatformRootIssuerCaPEM("");
        X509CertificateValidationResult valid = new X509CertificateValidationResult(true, new X509CertificateValidationType[0] );
        when(resource.certificateValidationService.validateRootCertificate(any())).thenReturn(valid);
        Response savePlatformData = resource.savePlatformData(data);
        Assert.assertEquals(Status.OK.getStatusCode(), savePlatformData.getStatus());
    }
    
    @Test
    public void testUnsuccessfulResponse() throws DuplicateEntryException, GeneralCryptoLibException, 
        CryptographicOperationException, URISyntaxException, IOException {
        prepareEnvironment();
        
        PlatformInstallationData data = new PlatformInstallationData();
        data.setLoggingEncryptionKeystoreBase64("ERE" + ENCRYPTION_KEYSTORE_BASE64);
        data.setLoggingSigningKeystoreBase64(SIGNING_KEYSTORE_BASE64);
        data.setPlatformRootCaPEM(platform);
        data.setPlatformRootIssuerCaPEM("");
        X509CertificateValidationResult valid = new X509CertificateValidationResult(true, new X509CertificateValidationType[0] );
        when(resource.certificateValidationService.validateRootCertificate(any())).thenReturn(valid);
        try {
            resource.savePlatformData(data);
            Assert.fail();
        } catch (IllegalStateException e){
            Assert.assertEquals(e.getMessage(), "EA - error while trying to initialize logging");
        }
    }
    
    private void prepareEnvironment() throws URISyntaxException, IOException {

        String externalSourceOfLoggingPasswords =
            Paths.get(getClass().getClassLoader().getResource("passwords/logging_EA.properties").toURI())
                .toAbsolutePath().toString();
        File externalSourceOfLoggingPasswordsAsFile = new File(externalSourceOfLoggingPasswords);

        String destinationDirectoryAsString =
            Paths.get(getClass().getClassLoader().getResource("productionPasswordsDir").toURI()).toAbsolutePath()
                .toString();
        Path destinationFileAsPath = Paths.get(destinationDirectoryAsString, loggingPasswordsFileName);
        File desintationDirectoryAsFile = new File(destinationFileAsPath.toAbsolutePath().toString());

        FileUtils.copyFile(externalSourceOfLoggingPasswordsAsFile, desintationDirectoryAsFile);
        System.setProperty("loggingpasswordsdirectory", destinationDirectoryAsString);
    }
}
