/*
 * Copyright (c) eHealth
 */

package be.fgov.ehealth.etee.crypto.examples;

import java.io.InputStream;

import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import be.fgov.ehealth.etee.crypto.decrypt.DataSealChecker;
import be.fgov.ehealth.etee.crypto.decrypt.DataSealCheckerBuilder;
import be.fgov.ehealth.etee.crypto.decrypt.UnsealedData;
import be.fgov.ehealth.etee.crypto.policies.OCSPPolicy;
import be.fgov.ehealth.etee.crypto.policies.SigningPolicy;
import be.fgov.ehealth.etee.crypto.status.CryptoResult;
import be.fgov.ehealth.etee.crypto.status.NotificationError;
import be.fgov.ehealth.etee.crypto.status.NotificationWarning;
import be.fgov.ehealth.etee.crypto.utils.Streams;

/**
 * An example that illustrates how to check the data seal from a received message.
 *
 * @author matla
 */
public class CheckDataSealExampleTest extends AbstractExample {

    public static final Logger LOGGER = LoggerFactory.getLogger(CheckDataSealExampleTest.class);

    @Test
    public void testCheckDataSealFromReceivedMessage() {
        /* Create an instance of DataSealChecker using the builder. */
        DataSealChecker dataSealChecker =
                DataSealCheckerBuilder.newBuilder().addOCSPPolicy(OCSPPolicy.NONE)
                        .addSigningPolicy(getTrustedCaCertificates(), SigningPolicy.EHEALTH_CERT, SigningPolicy.EID)
                        .build();

        /* Retrieve our sealed message */
        byte[] sealedMessage = Streams.getBytes(openSealedDataStream());

        /* Verify the data seal from the received message */
        CryptoResult<UnsealedData> result = dataSealChecker.validate(sealedMessage);

        /* Process the result that we received from the data seal checker */
        if (result.getFatal() == null) {  /* The verification operation succeeded */
            if (!result.hasErrors()) {    /* The result contains no errors or failures */
                /* Retrieve the information from the message */
                LOGGER.info("Author: " + result.getData().getAuthenticationCert().getSubjectDN());
                LOGGER.info("Signature: " + new String(result.getData().getSignature()));
                LOGGER.info("Signing time: " + result.getData().getSigningTime());
            } else {
                /*
                 * Retrieve the DataAuthenticationErrors or DataAuthenticationFailures, and do your specific security
                 * failure or error processing. BEFORE reading the data otherwise you'll get a RuntimeException.
                 */
                for (NotificationError error : result.getErrors()) {
                    LOGGER.error("Error: " + error);
                }
                for (NotificationWarning failure : result.getWarnings()) {
                    LOGGER.error("Failure: " + failure);
                }

                /* Retrieve the information from the message */
                LOGGER.info("Author: " + result.getData().getAuthenticationCert().getSubjectDN());
                LOGGER.info("Signing time: " + result.getData().getSigningTime());
            }
        } else {
            LOGGER.error("The message could not be verified, because: " + result.getFatal());
        }

    }

    private static InputStream openSealedDataStream() {
        return Thread.currentThread().getContextClassLoader().getResourceAsStream("test_examples/message_from_alice_for_bob.msg");
    }
}
