package com.github.jaystgelais.easymail;

import java.io.ByteArrayInputStream;
import java.io.StringWriter;
import java.net.URL;

import org.fit.cssbox.css.DOMAnalyzer;
import org.fit.cssbox.io.DOMSource;
import org.fit.cssbox.io.DefaultDOMSource;
import org.fit.cssbox.io.DocumentSource;
import org.fit.cssbox.io.StreamDocumentSource;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;

/**
 * Created by jaystgelais on 1/23/14.
 */
public final class StyleInliner {
    private StyleInliner() {

    }

    /**
     * Calculates teh effective styles of each HTML element and produces HTML output stripped of CSS classes and
     * effective style inlined as 'style' attributes.
     *
     * @param contentProvider Input to style inlining transformation.
     * @return HTML as String as product of style inlining transformation.
     * @throws HtmlTransformationException If any errors occur preventing the transformation of the inputted HTML
     *                                     document.
     */
    public static String inlineStyle(final HtmlContentProvider contentProvider) throws HtmlTransformationException {
        DocumentSource docSource = null;
        try {
            //Open the network connection
            docSource = new StreamDocumentSource(
                    new ByteArrayInputStream(contentProvider.getHtmlMessageContent().getBytes()), null, "text/html");

            //Parse the input document
            DOMSource parser = new DefaultDOMSource(docSource);
            Document doc = parser.parse();
            applyEffectiveStylesToStyleAttributes(doc, docSource.getURL());


            removeStyleElements(doc);

            javax.xml.transform.dom.DOMSource domSource = new javax.xml.transform.dom.DOMSource(doc);
            StringWriter writer = new StringWriter();
            StreamResult result = new StreamResult(writer);
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer transformer = tf.newTransformer();
            transformer.transform(domSource, result);
            return writer.toString();
        } catch (Exception e) {
            throw new HtmlTransformationException("Error occurred transforming HTML to use inline styles.", e);
        } finally {
            if (docSource != null) {
                try {
                    docSource.close();
                } catch (Exception e) {
                    throw new HtmlTransformationException("Error occurred transforming HTML to use inline styles.", e);
                }
            }
        }
    }

    private static void applyEffectiveStylesToStyleAttributes(final Document doc, final URL relativeUrl) {
        //Create the CSS analyzer
        DOMAnalyzer da = new DOMAnalyzer(doc, relativeUrl);
        da.attributesToStyles(); //convert the HTML presentation attributes to inline styles
        da.getStyleSheets(); //load the author style sheets
        da.stylesToDomInherited();
    }

    private static void removeStyleElements(final Document doc) {
        NodeList styleElements = doc.getElementsByTagName("style");
        for (int x = 0; x < styleElements.getLength(); x++) {
            styleElements.item(x).getParentNode().removeChild(styleElements.item(x));
        }
    }
}

@@ -72,16 +72,44 @@
 Stream;%0A
+import java.io.IOException;%0A
 import j
@@ -414,16 +414,49 @@
 odeList;
+%0Aimport org.xml.sax.SAXException;
 %0A%0Aimport
@@ -485,24 +485,73 @@
 ransformer;%0A
+import javax.xml.transform.TransformerException;%0A
 import javax
@@ -1429,50 +1429,8 @@
 y %7B%0A
-            //Open the network connection%0A
     
@@ -1452,23 +1452,16 @@
 ce = new
- Stream
 Document
@@ -1471,128 +1471,26 @@
 rce(
-%0A                    new ByteArrayInputStream(contentProvider.getHtmlMessageContent().getBytes()), null, %22text/html%22
+contentProvider
 );%0A
-%0A
     
@@ -1501,141 +1501,45 @@
     
-//Parse the input document%0A            DOMSource parser = new DefaultDOMSource(docSource);%0A            Document doc = parser.parse();
+Document doc = parseHtml(docSource);%0A
 %0A   
@@ -1611,18 +1611,16 @@
 URL());%0A
-%0A%0A
         
@@ -1666,430 +1666,34 @@
     
-javax.xml.transform.dom.DOMSource domSource = new javax.xml.transform.dom.DOMSource(doc);%0A            StringWriter writer = new StringWriter();%0A            StreamResult result = new StreamResult(writer);%0A            TransformerFactory tf = TransformerFactory.newInstance();%0A            Transformer transformer = tf.newTransformer();%0A            transformer.transform(domSource, result);%0A            return writer.toString(
+return getHtmlAsString(doc
 );%0A 
@@ -2154,32 +2154,1073 @@
        %7D%0A    %7D%0A%0A
+    private static String getHtmlAsString(final Document doc) throws TransformerException %7B%0A        javax.xml.transform.dom.DOMSource domSource = new javax.xml.transform.dom.DOMSource(doc);%0A        StringWriter writer = new StringWriter();%0A        StreamResult result = new StreamResult(writer);%0A        TransformerFactory tf = TransformerFactory.newInstance();%0A        Transformer transformer = tf.newTransformer();%0A        transformer.transform(domSource, result);%0A        return writer.toString();%0A    %7D%0A%0A    private static StreamDocumentSource newDocumentSource(final HtmlContentProvider contentProvider)%0A            throws IOException %7B%0A        return new StreamDocumentSource(new ByteArrayInputStream(contentProvider.getHtmlMessageContent().getBytes()),%0A                null, %22text/html%22);%0A    %7D%0A%0A    private static Document parseHtml(final DocumentSource docSource) throws SAXException, IOException %7B%0A        //Parse the input document%0A        DOMSource parser = new DefaultDOMSource(docSource);%0A        return parser.parse();%0A    %7D%0A%0A
     private stat

Clean Code Refactor of StyleInliner.inlineStyle()