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

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.KeyStoreException;

import org.apache.log4j.Logger;
import org.junit.Test;

import be.fgov.ehealth.etee.crypto.encrypt.DataSealer;
import be.fgov.ehealth.etee.crypto.encrypt.DataSealerException;
import be.fgov.ehealth.etee.crypto.encrypt.EncryptionToken;
import be.fgov.ehealth.etee.crypto.utils.IoUtils;


/**
 * This example illustrates the actions at Alice's (sender) side in order to protect a large authenticated message,
 * encrypted for Bob's (recipient) eyes only.
 * 
 * @author alde
 * 
 */
public class SealBigMessage extends AbstractExample  {

    private static final int ONE_SECOND = 1000;
	private static final Logger LOGGER = Logger.getLogger(SealBigMessage.class);
    
    @Test
    public final void sealBigMessageFromAliceToBob() throws IOException, DataSealerException, KeyStoreException {
        // 0. During initialisation, Alice creates her DataSealer that she can use to seal data.
        DataSealer alicesDataSealer = initSealing();

        // 1. Here Alice has a big message for Bob that must be
        // sealed to secure its confidentiality, integrity and authenticity.
        // For large messages the DataSealer streaming implementation should be used.
        InputStream bigClearMessageFromAliceToBob = openClearMessageStream();

        // 2. Prepare an output stream where the DataSealer implementation will write the sealed data to.
        OutputStream bigSealedMessageFromAliceToBob = openSealedDataStream();

        // 3. Get the public encryption key of the addressee, Bob, from the ETK-DEPOT web service.
        EncryptionToken bobsEtk = getBobsEtkFromEtkDepot();

        // 4. Seal the dataToBeSealed
        long start = System.currentTimeMillis();
        alicesDataSealer.seal(bobsEtk, bigClearMessageFromAliceToBob, bigSealedMessageFromAliceToBob);

        // 5. Flush and close the stream where the sealed data has been written to.
        bigSealedMessageFromAliceToBob.close();
        long end = System.currentTimeMillis();
        long duration = (end - start) / ONE_SECOND;
        LOGGER.info(String.format("Time elapsed %s seconds", String.valueOf(duration)));
    }

    private static InputStream openClearMessageStream() {
        return Thread.currentThread().
                      getContextClassLoader().
                      getResourceAsStream("test_examples/big_clear_message_from_alice_for_bob.msg");
    }
    
    /**
     * This method abstracts how Alice's message after data sealing is transported to Bob.
     * (This is application specific.)
     * 
     * @return a File containing the sealed message of Alice.
     */
    private static OutputStream openSealedDataStream() {
        return IoUtils.openFileOutputStream("target/big_sealed_message_from_alice_for_bob.msg");
    }
}
