package be.fgov.ehealth.technicalconnector.signature.impl;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import be.ehealth.technicalconnector.utils.ConnectorXmlUtils;
import be.fgov.ehealth.technicalconnector.signature.AdvancedElectronicSignatureEnumeration;
import be.fgov.ehealth.technicalconnector.signature.SignatureBuilderFactory;
import be.fgov.ehealth.technicalconnector.signature.domain.SignatureVerificationResult;
import be.fgov.ehealth.technicalconnector.signature.domain.XadesOption;

/**
 * Created by EH053 on 06/12/2016.
 */
public class XmlSignatureTest extends AbstractSignatureTest {


    @BeforeClass
    public static void initBuilder() throws Exception {
        builder = SignatureBuilderFactory.getSignatureBuilder(AdvancedElectronicSignatureEnumeration.XML);
    }

    @Test
    public void encapsulateDefaultLocation() throws Exception {
        String id = "_" + UUID.randomUUID()
                              .toString();
        String textToSign = "<doctosign xmlns='urn:be:fgov:ehealth:fake' Id='" + id + "'><content/><reason/></doctosign>";

        Map<String, Object> options = new HashMap<String, Object>();
        options.put(XadesOption.ENCAPSULATE, Boolean.TRUE);
        options.put(XadesOption.BASEURI, id);
        options.put(XadesOption.FOLLOWNESTEDMANIFEST, Boolean.TRUE);

        String signedDoc = new String(builder.sign(credential, textToSign.getBytes(), options), "UTF-8");

        Document doc = ConnectorXmlUtils.toDocument(signedDoc);

        Assert.assertEquals("Encapsulation nok", "doctosign", doc.getFirstChild()
                                                                 .getLocalName());
        Assert.assertEquals("Encapsulation nok", "Signature", doc.getFirstChild()
                                                                 .getLastChild()
                                                                 .getLocalName());

        SignatureVerificationResult result = builder.verify(signedDoc.getBytes("UTF-8"), options);
        Assert.assertTrue(result.isValid());

    }

    @Test
    public void encapsulateCustomLocation() throws Exception {
        String id = "_" + UUID.randomUUID()
                              .toString();
        String textToSign = "<doctosign xmlns='urn:be:fgov:ehealth:fake' Id='" + id + "'><content/><reason/></doctosign>";

        Map<String, Object> options = new HashMap<String, Object>();
        options.put(XadesOption.ENCAPSULATE, Boolean.TRUE);
        options.put(XadesOption.ENCAPSULATE_XPATH, "/*[local-name()='doctosign']/*[local-name()='reason']");
        options.put(XadesOption.BASEURI, id);
        options.put(XadesOption.FOLLOWNESTEDMANIFEST, Boolean.TRUE);

        String signedDoc = new String(builder.sign(credential, textToSign.getBytes(), options), "UTF-8");

        Node signedNode = ConnectorXmlUtils.toDocument(signedDoc)
                                           .getFirstChild();

        Assert.assertEquals("Encapsulation nok", "doctosign", signedNode.getLocalName());

        NodeList childNodes = signedNode.getChildNodes();
        Assert.assertEquals(3, childNodes.getLength());
        Assert.assertEquals("doctosign/content nok", "content", childNodes.item(0)
                                                                          .getLocalName());
        Assert.assertEquals("doctosign/Signature nok", "Signature", childNodes.item(1)
                                                                              .getLocalName());
        Assert.assertEquals("doctosign/reason nok", "reason", childNodes.item(2)
                                                                        .getLocalName());

        SignatureVerificationResult result = builder.verify(signedDoc.getBytes("UTF-8"), options);
        Assert.assertTrue(result.isValid());

    }

}