/*
 * Copyright (c) eHealth
 */
package be.fgov.ehealth.etee.crypto.examples;

import java.io.IOException;
import java.io.InputStream;

import javax.crypto.SecretKey;

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

import be.fgov.ehealth.etee.crypto.decrypt.DataUnsealer;
import be.fgov.ehealth.etee.crypto.decrypt.UnsealedData;
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.SecretKeyUtils;
import be.fgov.ehealth.etee.crypto.utils.Streams;


/**
 * An example that illustrates the actions at Bob's (recipient) side in order to read and verify a sealed data message from Alice (sender).
 *
 * @author jeh
 */
public class UnsealByUnknown extends AbstractExample {

    private static final Logger LOGGER = LoggerFactory.getLogger(UnsealByUnknown.class);

    @Test
    public final void unsealMessageByUnknown() throws IOException {
        // 0. During initialisation, Bob creates his DataUnsealer that he can use to
        // decrypt and verify incomming sealed data.
        DataUnsealer bobsDataUnsealer = initUnsealing();

        // 1. Now Bob receives some 'sealed data'
        byte[] sealedData = Streams.getBytes(openSealedDataStream());

        // 2. Get the key from the KGSS web service.
        String base64EncodedKek = getKekFromKgss();
        SecretKey kek = SecretKeyUtils.getSecretKey(base64EncodedKek);

        // 2. Unseal the received message
        CryptoResult<UnsealedData> rslt = bobsDataUnsealer.unseal(sealedData, kek);


        // 3. Process the result of the unseal operation
        if (rslt.getFatal() == null) { // 3.A. The decryption operation succeeded
            if (!rslt.hasErrors()) { // 3.A.A. There are no errors or failures
                // 3.A.A.1. Get the author
                LOGGER.info("from author: " + rslt.getData().getAuthenticationCert().getSubjectDN());
                // 3.A.A.2. Get the unsealed data
                InputStream unsealedDataStream = rslt.getData().getContent();
                byte[] unsealedData = Streams.getBytes(unsealedDataStream);
                LOGGER.info("unsealed data: " + new String(unsealedData));

            } else { // 3.A.B. The data authenticity is not OK
                // 3.A.B.1. Get the DataAuthenticationErrors or DataAuthenticationFailures
                // and do your specific security failure or error processing
                // BEFORE reading the unsealed data (otherwise you will have an RuntimeException
                for (NotificationError error : rslt.getErrors()) {
                    // e.g.
                    LOGGER.error("error: " + error);
                }
                for (NotificationWarning failure : rslt.getWarnings()) {
                    // e.g.
                    LOGGER.error("failure: " + failure);
                }
                // 3.A.B.2. After checking the errors and failures you can get the unsealed data
                InputStream unsealedDataStream = rslt.getData().getContent();
                byte[] unsealedData = Streams.getBytes(unsealedDataStream);
                LOGGER.info("unsealed data: " + new String(unsealedData));
            }
        } else { // 3.B the decryption failed, there is no decrypted data
            LOGGER.warn("the msg could not be unsealed, because:" + rslt.getFatal());
        }
    }

    /**
     * Method abstracts the way to get the KEK with given kekId from the KGSS web service.
     *
     * @return base 64 encoded KEK
     */
    private static String getKekFromKgss() {
        return ExampleProperties.getBase64EncodedKek();
    }

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