package net.sourceforge.rtf.format;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.text.FieldPosition;

import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import net.sourceforge.rtf.SimpleErrorListener;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class DefaultHtmlToRTFStringFormat extends DefaultRTFCodeStringFormat {
	/**
	 * Default logger.
	 **/
	private static Log logger = LogFactory.getLog(DefaultHtmlToRTFStringFormat.class);

	private Transformer t = null;
	//private XMLReader reader = null;
	
	public DefaultHtmlToRTFStringFormat() {
		TransformerFactory tf = TransformerFactory.newInstance();
		try {
			t = tf.newTransformer(new StreamSource(this.getClass().getClassLoader().getResourceAsStream("xhtml2rtf.xsl")));
			//SAXParserFactory parserFactory = SAXParserFactory.newInstance();
			//SAXParser parser = parserFactory.newSAXParser();
			//reader = parser.getXMLReader();
			//reader.setEntityResolver(new CachedHtmlDtdEntityResolver());
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	public StringBuffer format(Object obj, StringBuffer stringbuffer,
			FieldPosition fieldposition) {
		if (!(obj instanceof String)) {
			return super.format(obj, stringbuffer, fieldposition);
		}
		
		String strObj = (String)obj;
		if (strObj.indexOf("</") == -1) {
			return super.format(obj, stringbuffer, fieldposition);
		}
		
		try {
			//strObj = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"><body>" + strObj + "</body>";
			//strObj = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"xhtml1-transitional.dtd\"><body>" + strObj + "</body>";
			//strObj = "<!DOCTYPE stylesheet [<!ENTITY agrave \"&#224;\"><!ENTITY nbsp \"&#160;\"><!ENTITY egrave \"&#232;\"><!ENTITY igrave \"&#236;\"><!ENTITY ograve \"&#242;\"><!ENTITY ugrave \"&#249;\">]><body>" + strObj + "</body>";
			strObj = "<body>" + strObj + "</body>";
			Source s = null;
			try {
				s = new StreamSource(new ByteArrayInputStream(strObj.getBytes("UTF-8")));
				//s = new SAXSource(reader, new InputSource(new ByteArrayInputStream(strObj.getBytes("UTF-8"))));
			} catch (Exception e) {
				e.printStackTrace();
			}
			ByteArrayOutputStream baosResult = new ByteArrayOutputStream();
			Result r = new StreamResult(baosResult);
			
			SimpleErrorListener simpleErrorListener = new SimpleErrorListener(logger);
			t.setErrorListener(simpleErrorListener);
			t.transform(s, r);
			if (simpleErrorListener.hasErrors()) {
				StringBuffer msg = new StringBuffer("Error parsing html:\n\r");
				msg.append(simpleErrorListener.getAllMessages());
				msg.append("Content of the original html text:\n\r");
				msg.append(obj);
				logger.error(msg);
				return super.format(msg.toString(), stringbuffer, fieldposition);
			}
			
			return new StringBuffer(baosResult.toString());
		} catch (TransformerException e) {
			StringBuffer msg = new StringBuffer("Error: " + e.getLocalizedMessage() + " parsing html field:" + fieldposition + " containing the value:\n\r" + obj);
			logger.error(msg.toString());
			e.printStackTrace();
			return msg;
			//return super.format(obj, stringbuffer, fieldposition);
		}
	}
}
