/* 
 * Copyright (c) eHealth 
 */
package be.ehealth.technicalconnector.utils;

import java.io.ByteArrayInputStream;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.junit.Assert;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import be.ehealth.technicalconnector.jaxb.DummyChild;
import be.ehealth.technicalconnector.jaxb.DummyRoot;
import be.fgov.ehealth.technicalconnector.domain.pojo.SimplePojo;
import be.fgov.ehealth.technicalconnector.tests.utils.XmlAsserter;


/**
 * Basic test to marshall with a DataHandler
 * 
 * @author EHP
 * 
 * 
 * 
 */
public class MarshallerHelperTest {

    private static final Logger LOG = LoggerFactory.getLogger(MarshallerHelperTest.class);

    private MarshallerHelper<DummyRoot, DummyRoot> rootHelper = new MarshallerHelper<DummyRoot, DummyRoot>(DummyRoot.class, DummyRoot.class);

    private MarshallerHelper<DummyChild, DummyChild> noRootHelper = new MarshallerHelper<DummyChild, DummyChild>(DummyChild.class, DummyChild.class);

    private MarshallerHelper<SimplePojo, SimplePojo> pojoHelper = new MarshallerHelper<SimplePojo, SimplePojo>(SimplePojo.class, SimplePojo.class);

    private static final String ROOT = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><ns2:root xmlns:ns2=\"root\"><base64>aGVsbG8=</base64></ns2:root>";

    private static final String NO_ROOT = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><ns:DummyChild xmlns:ns=\"urn:be:fgov:ehealth:technicalconnector:jaxb\"><base64>Y2hpbGQ=</base64></ns:DummyChild>";


    @Test
    public void toDocumentWithObjectRoot() throws Exception {
        Document actual = rootHelper.toDocument(createDummyRoot(null));
        XmlAsserter.assertSimilar(createDummyRootDocument(), actual);
    }


    @Test
    public void toDocumentWithObjectNoRoot() throws Exception {

        Document actual = noRootHelper.toDocument(createDummyChild());
        XmlAsserter.assertSimilar(createDummyChildDocument(), actual);

    }

    @Test
    public void toObjectWithByteArrayRoot() throws Exception {
        DummyRoot actual = rootHelper.toObject(ROOT.getBytes());
        Assert.assertEquals(createDummyRoot(null), actual);
    }

    @Test
    public void toObjectWithByteArrayNoRoot() throws Exception {
        DummyChild actual = noRootHelper.toObject(NO_ROOT.getBytes());
        Assert.assertEquals(createDummyChild(), actual);
    }

    @Test
    public void toObjectWithInputStreamRoot() throws Exception {
        DummyRoot actual = rootHelper.toObject(new ByteArrayInputStream(ROOT.getBytes()));
        Assert.assertEquals(createDummyRoot(null), actual);
    }

    @Test
    public void toObjectWithInputStreamNoRoot() throws Exception {
        DummyChild actual = noRootHelper.toObject(new ByteArrayInputStream(NO_ROOT.getBytes()));
        Assert.assertEquals(createDummyChild(), actual);
    }


    @Test
    public void toObjectWithNodeRoot() throws Exception {

        DummyRoot actual = rootHelper.toObject(createDummyRootDocument().getFirstChild());
        Assert.assertEquals(createDummyRoot(null), actual);
    }

    @Test
    public void toObjectWithNodeNoRoot() throws Exception {

        DummyChild actual = noRootHelper.toObject(createDummyChildDocument().getFirstChild());
        Assert.assertEquals(createDummyChild(), actual);

    }


    @Test
    public void toObjectWithStringRoot() throws Exception {
        DummyRoot actual = rootHelper.toObject(ROOT);
        Assert.assertEquals(createDummyRoot(null), actual);
    }

    @Test
    public void toObjectWithStringNoRoot() throws Exception {
        DummyChild actual = noRootHelper.toObject(NO_ROOT);
        Assert.assertEquals(createDummyChild(), actual);
    }


    @Test
    public void toStringWithObjectRoot1() throws Exception {
        DataHandler content = new DataHandler(new FileDataSource(ConnectorIOUtils.getResourceAsFile("/examples/ID1.xml")));
        DummyRoot root = createDummyRoot(content);
        String actual = rootHelper.toString(root);
        LOG.debug(actual);
        Assert.assertFalse(StringUtils.isEmpty(actual));
    }

    @Test
    public void toStringWithSimplePojo() {
        String actual = pojoHelper.toString(createSimplePojo());
        System.out.println(actual);
    }

    @Test
    public void toStringWithObjectRoot2() throws Exception {
        DummyRoot root = createDummyRoot(null);
        String actual = rootHelper.toString(root);
        LOG.debug(actual);
        Assert.assertFalse(StringUtils.isEmpty(actual));
        Assert.assertEquals(ROOT, actual);
    }

    @Test
    public void toStringWithObjectNoRoot() throws Exception {
        DummyChild child = createDummyChild();
        String actual = noRootHelper.toString(child);
        LOG.debug(actual);
        Assert.assertFalse(StringUtils.isEmpty(actual));
        XmlAsserter.assertSimilar(NO_ROOT, actual);
    }

    @Test
    public void toXMLByteArrayWithObjectRoot() throws Exception {
        DummyRoot root = createDummyRoot(null);
        byte[] actual = rootHelper.toXMLByteArray(root);
        LOG.debug(new String(actual));
        Assert.assertFalse(ArrayUtils.isEmpty(actual));
        Assert.assertArrayEquals(ROOT.getBytes(), actual);

    }

    @Test
    public void toXMLByteArrayWithObjectNoRoot() throws Exception {
        DummyChild child = createDummyChild();
        byte[] actual = noRootHelper.toXMLByteArray(child);
        LOG.debug(new String(actual));
        Assert.assertFalse(ArrayUtils.isEmpty(actual));
        XmlAsserter.assertSimilar(NO_ROOT, new String(actual));
    }

    private static DummyChild createDummyChild() {
        DummyChild child = new DummyChild();
        child.setBase64("child".getBytes());
        return child;
    }

    private static DummyRoot createDummyRoot(DataHandler content) {
        DummyRoot root = new DummyRoot();
        root.setContent(content);
        root.setBase64("hello".getBytes());
        return root;
    }

    private static SimplePojo createSimplePojo() {
        SimplePojo root = new SimplePojo();
        root.setId("test");
        root.setContent("hello".getBytes());
        return root;
    }

    private static Document createDummyRootDocument() throws ParserConfigurationException {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        Document expected = dbf.newDocumentBuilder()
                               .newDocument();
        Element rootNode = expected.createElementNS("root", "root:root");
        Element base64node = expected.createElement("base64");
        base64node.setTextContent("aGVsbG8=");
        rootNode.appendChild(base64node);
        expected.appendChild(rootNode);
        return expected;
    }

    private static Document createDummyChildDocument() throws Exception {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        Document expected = dbf.newDocumentBuilder()
                               .newDocument();
        Element rootNode = expected.createElementNS("urn:be:fgov:ehealth:technicalconnector:jaxb", "ns:DummyChild");
        Element base64node = expected.createElement("base64");
        base64node.setTextContent("Y2hpbGQ=");
        rootNode.appendChild(base64node);
        expected.appendChild(rootNode);

        return expected;
    }
}