/*
 * 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.awt.BorderLayout;
import java.awt.Color;
import java.awt.Desktop;
import java.awt.Dimension;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.URI;

import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.SizeRequirements;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultCaret;
import javax.swing.text.Element;
import javax.swing.text.View;
import javax.swing.text.ViewFactory;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.InlineView;
import javax.swing.text.html.ParagraphView;

import org.apache.log4j.Layout;
import org.apache.log4j.PatternLayout;

import fr.mines_stetienne.ci.saref.SAREF;

public class ConsolePanel extends JPanel {

	final JTextPane txtConsole;
	final JScrollPane scroll;

	public ConsolePanel() {
		super(new BorderLayout());
		setMinimumSize(new Dimension(400, 150));
		setPreferredSize(new Dimension(400, 150));
		setBorder(BorderFactory.createLineBorder(Color.BLACK));
		txtConsole = new JTextPane();
		txtConsole.setEditorKit(new HTMLEditorKit() {
			@Override
			public ViewFactory getViewFactory() {

				return new HTMLFactory() {
					public View create(Element e) {
						View v = super.create(e);
						if (v instanceof InlineView) {
							return new InlineView(e) {
								public int getBreakWeight(int axis, float pos, float len) {
									return GoodBreakWeight;
								}

								public View breakView(int axis, int p0, float pos, float len) {
									if (axis == View.X_AXIS) {
										checkPainter();
										int p1 = getGlyphPainter().getBoundedPosition(this, p0, pos, len);
										if (p0 == getStartOffset() && p1 == getEndOffset()) {
											return this;
										}
										return createFragment(p0, p1);
									}
									return this;
								}
							};
						} else if (v instanceof ParagraphView) {
							return new ParagraphView(e) {
								protected SizeRequirements calculateMinorAxisRequirements(int axis,
										SizeRequirements r) {
									if (r == null) {
										r = new SizeRequirements();
									}
									float pref = layoutPool.getPreferredSpan(axis);
									float min = layoutPool.getMinimumSpan(axis);
									// Don't include insets, Box.getXXXSpan will include them.
									r.minimum = (int) min;
									r.preferred = Math.max(r.minimum, (int) pref);
									r.maximum = Integer.MAX_VALUE;
									r.alignment = 0.5f;
									return r;
								}

							};
						}
						return v;
					}
				};
			}
		});
		txtConsole.setContentType("text/html");
		txtConsole.setAutoscrolls(true);
		txtConsole.setEditable(false);
		txtConsole.addHyperlinkListener(new HyperlinkListener() {
			@Override
			public void hyperlinkUpdate(HyperlinkEvent e) {
				if (HyperlinkEvent.EventType.ACTIVATED.equals(e.getEventType())) {
					try {
						URI uri = e.getURL().toURI();
						Desktop.getDesktop().browse(uri);
					} catch (Exception ex) {
						System.err.println(ex);
					}
				}
			}
		});
		((DefaultCaret) txtConsole.getCaret()).setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);

		final Layout layout = new PatternLayout("%-5p %m%n");
		final org.apache.log4j.Logger loggerBase = org.apache.log4j.Logger.getLogger(SAREF.LOGGER_BASE);
		loggerBase.addAppender(new JTextAreaAppender(layout, txtConsole));

		scroll = new JScrollPane(txtConsole, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
				JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
		scroll.getViewport().add(txtConsole);
		scroll.setDoubleBuffered(true);
		add(scroll);
		update(getGraphics());

	}

	public void clear() {
		txtConsole.setText("");
	}

	public void reportInfo(String header, String msg) {
		HTMLDocument doc = (HTMLDocument) txtConsole.getStyledDocument();
		String info = String.format("<h2>%s</h2> %s", header, msg);
		try {
			doc.insertBeforeEnd(doc.getDefaultRootElement(), info);
		} catch (BadLocationException e) {
		} catch (IOException e1) {
		}
		txtConsole.update(txtConsole.getGraphics());
		txtConsole.setCaretPosition(txtConsole.getDocument().getLength());
	}

	public void reportError(Exception ex) {
		HTMLDocument doc = (HTMLDocument) txtConsole.getStyledDocument();
		StringWriter sw = new StringWriter();
		ex.printStackTrace(new PrintWriter(sw));
		String errorStr = sw.toString().replace("<", "&lt;");
		String error = String.format("<h2>Some errors were detected by the SAREF Pipeline</h2> %s", errorStr);
		try {
			doc.insertBeforeEnd(doc.getDefaultRootElement(), error);
		} catch (BadLocationException e) {
		} catch (IOException e1) {
		}
		txtConsole.update(txtConsole.getGraphics());
		txtConsole.setCaretPosition(txtConsole.getDocument().getLength());
	}

}
