package net.sourceforge.rtf;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.Writer;

import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.rtf.RTFEditorKit;

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

public class RTFConverter {
	
	private static final String RTF_CHUNK_SUFFIX = "}}}";
	private static final String RTF_CHUNK_PREFIX = "{\\rtf1\\ansi\\ansicpg1252\\deff0{\\fonttbl{\\f0\\fnil\\fcharset0 Arial;}}{{";
	/**
	 * Default logger.
	 */
	private static Log logger = LogFactory.getLog(RTFConverter.class);

	public static String convertTextString(String p_in) throws IOException {
		// test for null inputs to avoid java.lang.NullPointerException when
		// input is null
		if (p_in != null) {
			RTFEditorKit kit = new RTFEditorKit();
			Document doc = kit.createDefaultDocument();
			try {
				kit.read(new StringReader(p_in), doc, 0);
				return doc.getText(0, doc.getLength());
			} catch (BadLocationException e) {
				throw new RuntimeException(e);
			}
		} else {
			return null;
		}
	}
	
	public static String convertRtfChunk(String chunk) throws IOException {
		String result = RTFConverter.convertTextString(RTF_CHUNK_PREFIX + chunk + RTF_CHUNK_SUFFIX);
		result = StringUtils.strip(result, "\n\r");
		return result;
	}
	
	public static void convertStream(InputStream input, OutputStream output) throws IOException {
		BufferedInputStream is = new BufferedInputStream(input, 4096);
		InputStreamReader isr = new InputStreamReader(is);

		convertStream(isr, output);
	}
	
	public static void convertStream(Reader input, OutputStream output) throws IOException {
		char[] carattere = new char[1];
		
		OutputStreamWriter outWriter = new OutputStreamWriter(output);
		
		int len = input.read(carattere);
		while (len != -1) {
			processChar(input, outWriter, carattere);
			len = input.read(carattere);
		}
		outWriter.flush();
	}

	private static void processChar(Reader isr,
			Writer outWriter, char[] carattere) throws IOException {

		if (carattere[0] != '[') {
			outWriter.write(carattere);
		} else {
			processChunk(isr, outWriter, carattere);
		}
		
	}

	private static void processChunk(Reader isr, Writer outWriter, char[] carattere) throws IOException {
		String chunk = getChunk(isr, carattere);
		analyseChunk(chunk);
		String convertedChunk = convertRtfChunk(chunk);
		convertedChunk = stripBrackets(convertedChunk);
		
		if (logger.isDebugEnabled()) {
			logger.debug("Writing converted chunk: " + convertedChunk);
		}
		outWriter.write(convertedChunk);
	}

	private static void analyseChunk(String chunk) {
		if (logger.isDebugEnabled()) {
			logger.debug("Converting chunk: " + chunk);
		}
		//int ctrOpenCurly = StringUtils.countMatches(chunk, "{");
		//int ctrCloseCurly = StringUtils.countMatches(chunk, "}");
		//logger.info("...the chunk contains " + ctrOpenCurly + " open curly brackets and " + ctrCloseCurly + " close curly brackets.");
	}

	private static String stripBrackets(String convertedChunk) {
		return convertedChunk.replace("[", "").replace("]", "");
	}

	private static String getChunk(Reader isr, char[] carattere)	throws IOException {
		String chunk = "";
		while (carattere[0] != ']') {
			chunk += carattere[0] + "";
			int len = isr.read(carattere);
		}
		chunk += carattere[0] + "";
		return chunk;
	}
}
