/*
 * 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.cryptolib.asymmetric.xml.signer.factory;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.asymmetric.xml.signer.configuration.XmlDigitalSignerPolicyFromProperties;
import com.scytl.cryptolib.commons.constants.Constants;
import com.scytl.cryptolib.primitives.primes.utils.PemUtils;

public class XmlDigitalSignerTest {

    private static String RSA_PRIVATE_KEY_PATH = "/data/rsaPrivateKey.pem";

    private static String RSA_PUBLIC_KEY_PATH = "/data/rsaPublicKey.pem";

    private static String XML_FILE_TO_SIGN_PATH =
        "/data/sample_xml_file.xml";

    private static String SIGNED_XML_FILE_PATH =
        "target/signed_sample_xml_file.xml";

    private static String SIGNATURE_PARENT_NODE = "element1";

    private static CryptoXmlDigitalSigner _cryptoXmlDigitalSigner;

    @BeforeClass
    public static void setUp()
            throws GeneralCryptoLibException, GeneralSecurityException {

        Security.addProvider(new BouncyCastleProvider());

        _cryptoXmlDigitalSigner =
            new XmlDigitalSignerFactory(
                new XmlDigitalSignerPolicyFromProperties(
                    Constants.CRYPTOLIB_POLICY_PROPERTIES_FILE_PATH))
                .create();
    }

    @AfterClass
    public static void tearDown() {
        Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);

        File file = new File(SIGNED_XML_FILE_PATH);
        if (file.exists()) {
            file.delete();
        }
    }

    @Test
    public void testSignAndVerifyXmlFile()
            throws IOException, GeneralCryptoLibException {

        String pemStrIn = loadPem(RSA_PRIVATE_KEY_PATH);
        PrivateKey privateKey = PemUtils.privateKeyFromPem(pemStrIn);

        pemStrIn = loadPem(RSA_PUBLIC_KEY_PATH);
        PublicKey publicKey = PemUtils.publicKeyFromPem(pemStrIn);

        InputStream xmlInStream =
            getClass().getResourceAsStream(XML_FILE_TO_SIGN_PATH);

        OutputStream xmlOutStream =
            new FileOutputStream(SIGNED_XML_FILE_PATH);

        _cryptoXmlDigitalSigner.sign(privateKey, null, xmlInStream,
            xmlOutStream, SIGNATURE_PARENT_NODE);

        InputStream signedXmlInStream =
            new FileInputStream(SIGNED_XML_FILE_PATH);

        boolean signatureVerified =
            _cryptoXmlDigitalSigner.verify(publicKey, signedXmlInStream,
                SIGNATURE_PARENT_NODE);

        Assert.assertTrue(signatureVerified);
    }
    
    private String loadPem(String resource) throws IOException {
        StringBuilder pem = new StringBuilder();
        try (InputStream stream = getClass().getResourceAsStream(resource);
                Reader reader = new InputStreamReader(stream,
                    StandardCharsets.UTF_8);) {
            int c;
            while ((c = reader.read()) != -1) {
                pem.append((char) c);
            }
        }
        return pem.toString();
    }
}
