/*
 * Copyright 2020 ETSI
 * 
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright notice, 
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice, 
 *    this list of conditions and the following disclaimer in the documentation 
 *    and/or other materials provided with the distribution.
 * 3. Neither the name of the copyright holder nor the names of its contributors 
 *    may be used to endorse or promote products derived from this software without 
 *    specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package fr.mines_stetienne.ci.saref.gui;

import java.io.IOException;

import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.html.HTMLDocument;

import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.Layout;
import org.apache.log4j.Level;
import org.apache.log4j.spi.ErrorCode;
import org.apache.log4j.spi.LoggingEvent;
import org.commonmark.node.Node;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.HtmlRenderer;

import fr.mines_stetienne.ci.saref.SAREF;

/**
 * @author Omar Qawasmeh
 * 
 * @organization Ecole des Mines de Saint Etienne
 */
public class JTextAreaAppender extends AppenderSkeleton {

	private static final String NEW_LINE = System.getProperty("line.separator");

	private final JTextPane jTextPane;
	private final HTMLDocument doc;
	private static final Parser parser = Parser.builder().build();
	private String loggerName;

	public JTextAreaAppender(final Layout layout, final JTextPane jTextPane) {
		super();
		if (jTextPane == null) {
			throw new NullPointerException();
		}
		this.jTextPane = jTextPane;
		this.doc = (HTMLDocument) jTextPane.getDocument();
		this.layout = layout;
	}

	/**
	 * This method is called by the {@link AppenderSkeleton#doAppend} method.
	 * 
	 */
	@Override
	protected void append(LoggingEvent event) {
		if (layout == null) {
			errorHandler.error("No layout for appender " + name, null, ErrorCode.MISSING_LAYOUT);
			return;
		}
		final String message = layout.format(event);	    
	    Node document = parser.parse(message);
	    HtmlRenderer renderer = HtmlRenderer.builder().build();
	    String html = renderer.render(document);

	    
	    String loggerName = event.getLoggerName().substring(SAREF.LOGGER_BASE.length()+1);
	    if(!loggerName.equals(this.loggerName)) {
	    	this.loggerName = loggerName;
	    	try {
				doc.insertBeforeEnd(doc.getDefaultRootElement(), String.format("<h2>%s</h2>", loggerName));
				jTextPane.setCaretPosition(jTextPane.getDocument().getLength());
				jTextPane.update(jTextPane.getGraphics());
			} catch (BadLocationException e) {
				errorHandler.error("BadLocationException for appender " + name, e, ErrorCode.GENERIC_FAILURE);
				return;
			} catch (IOException e1) {
				errorHandler.error("IOException for appender " + name, e1, ErrorCode.GENERIC_FAILURE);
				return;
			}
	    }
	    		
	    final String output;
		
//		Level level = event.getLevel();
//		if(Level.FATAL.equals(level)) {
//			output = String.format("<div style=\"color: red\">%s</div>", html);
//		} else if(Level.ERROR.equals(level)) {
//			output = String.format("<div style=\"color: red\">%s</div>", html);
//		} else if(Level.WARN.equals(level)) {
//			output = String.format("<div style=\"color: black\">%s</div>", html);
//		} else if(Level.INFO.equals(level)) {
//			output = String.format("<div style=\"color: black\">%s</div>", html);
//		} else {
//			output = String.format("<div style=\"color: gray\">%s</div>", html);
//		}
	    output = html;
	    
	    try {
			doc.insertBeforeEnd(doc.getDefaultRootElement(), output);
		} catch (BadLocationException e) {
			errorHandler.error("BadLocationException for appender " + name, e, ErrorCode.GENERIC_FAILURE);
			return;
		} catch (IOException e1) {
			errorHandler.error("IOException for appender " + name, e1, ErrorCode.GENERIC_FAILURE);
			return;
		}
		
		if (layout.ignoresThrowable() && event.getThrowableStrRep() != null) {
			String errorStr = String.join("<br>\n", event.getThrowableStrRep()).replace("<", "&lt;");
			String error = String.format("<pre style=\"color: magenta\"><code>%s</code></pre>", errorStr);
			try {
				doc.insertBeforeEnd(doc.getDefaultRootElement(), error);
			} catch (BadLocationException e) {
				errorHandler.error("BadLocationException for appender " + name, e, ErrorCode.GENERIC_FAILURE);
				return;
			} catch (IOException e1) {
				errorHandler.error("IOException for appender " + name, e1, ErrorCode.GENERIC_FAILURE);
				return;
			}
		}
		jTextPane.update(jTextPane.getGraphics());
		jTextPane.setCaretPosition(jTextPane.getDocument().getLength());
	}

	public boolean requiresLayout() {
		return true;
	}

	public synchronized void close() {
		if (this.closed)
			return;
		this.closed = true;
	}

}
