package be.ehealth.technicalconnector.service.timestamp;

import java.io.InputStream;

import org.junit.BeforeClass;
import org.junit.Test;
import org.w3._2000._09.xmldsig.DigestMethod;

import be.ehealth.technicalconnector.enumeration.MimeType;
import be.ehealth.technicalconnector.idgenerator.IdGeneratorFactory;
import be.ehealth.technicalconnector.utils.ConnectorCryptoUtils;
import be.ehealth.technicalconnector.utils.ConnectorIOUtils;
import be.ehealth.technicalconnector.utils.MarshallerHelper;
import be.ehealth.technicalconnector.validator.ValidatorHelper;
import be.fgov.ehealth.technicalconnector.tests.utils.LoggingUtils;
import be.fgov.ehealth.technicalconnector.tests.utils.XmlAsserter;
import oasis.names.tc.dss._1_0.core.schema.*;

/**
 * Time Stamping Service Integration Tests This test shows the use of the Time Stamping Consult Service through the use of the Technical
 * Connector.
 * 
 * All Tests requir the following pre-requisites to be met: <li>An eHealth certificate with access to the Time Stamping service
 * 
 * @author EHP
 */
public class TimeStampingAuthorityTest {

    private static final String XSD_DSS = "/external/XSD/oasis-dss-core-schema-v1.0-os.xsd";


    @SuppressWarnings("javadoc")
    @BeforeClass
    public static void init() throws Exception {
        LoggingUtils.bootstrap();
    }


    /**
     * Test the SignRequest operation from the Time Stamping Authority Service through the use of the Technical Connector. This test creates
     * a time stamp for a given document which can be used later to validate the document.
     * 
     * The following main steps are done: <li>Create the parameters of the new message <li>Invoke the technical connector <li>Verify the
     * response
     * 
     * @author EHP
     */
    @Test
    public void signRequestWithDocument() throws Exception {


        String requestId = IdGeneratorFactory.getIdGenerator()
                                             .generateId();
        String profile = "urn:ehealth:profiles:timestamping:1.0";

        // read out a sample file
        InputStream is = ConnectorIOUtils.getResourceAsStream("/be.ehealth.technicalconnector.properties");
        byte[] base64Document = ConnectorIOUtils.getBytes(is);

        SignRequest request = new SignRequest();
        request.setRequestID(requestId);
        request.setProfile(profile);

        InputDocuments inputDocuments = new InputDocuments();
        DocumentType document = new DocumentType();
        Base64Data inputDocument = new Base64Data();
        inputDocument.setMimeType(MimeType.plaintext.getValue());
        inputDocument.setValue(base64Document);
        document.setBase64Data(inputDocument);

        inputDocuments.getDocument()
                      .add(document);
        request.setInputDocuments(inputDocuments);

        validate(request);

    }

    /**
     * Test the SingRequest opeation with the hash of the document as input
     * 
     * @author EHP
     */
    @Test
    public void signRequestWithDocumentHash() throws Exception {

        String requestId = IdGeneratorFactory.getIdGenerator()
                                             .generateId();
        String profile = "urn:ehealth:profiles:timestamping:2.0";
        String hashAlgo = "SHA-256";

        // Calculate the hash of the sample file
        InputStream is = ConnectorIOUtils.getResourceAsStream("/be.ehealth.technicalconnector.properties");
        byte[] hash = ConnectorCryptoUtils.calculateDigest(hashAlgo, ConnectorIOUtils.getBytes(is));

        SignRequest request = new SignRequest();
        request.setRequestID(requestId);
        request.setProfile(profile);

        InputDocuments inputDocuments = new InputDocuments();
        DocumentHash document = new DocumentHash();
        DigestMethod method = new DigestMethod();
        method.setAlgorithm(hashAlgo);
        document.setDigestMethod(method);
        document.setDigestValue(hash);

        inputDocuments.getDocumentHash()
                      .add(document);
        request.setInputDocuments(inputDocuments);

        validate(request);

    }


    private static void validate(SignRequest request) throws Exception {
        ValidatorHelper.validate(request, request.getClass(), XSD_DSS);

        MarshallerHelper<SignRequest, SignRequest> helper = new MarshallerHelper<SignRequest, SignRequest>(SignRequest.class, SignRequest.class);
        String requestString = helper.toString(request);
        Object xmlObject = helper.toObject(requestString);

        ValidatorHelper.validate(xmlObject, xmlObject.getClass(), XSD_DSS);
        XmlAsserter.assertSimilar(requestString, xmlObject);
    }


}
