/*
 * jNPad v0.3 - jNPad's an Simple Text Editor written in Java
 *
 * Copyright (C) 2014-2017  rgs
 *
 * Require JDK 1.6 (or later)
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 *
 *
 * Info, Questions, Suggestions & Bugs Report to rgsevero@gmail.com
 */

package jnpad.ui;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.HeadlessException;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.JButton;
import javax.swing.JEditorPane;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;

import jnpad.GUIUtilities;
import jnpad.JNPadBundle;
import jnpad.util.Utilities;

/**
 * 
 * @version 0.3
 * @since   jNPad v0.1
 */
public final class ExceptionDialog extends EscapableDialog {
  JPanel                      contentPane;
  JLabel                      lbIntro          = new JNPadLabel();
  JEditorPane                 editorPane       = new JEditorPane();
  JScrollPane                 scrollPane       = new JScrollPane();
  JPanel                      pnButtons        = new JPanel();
  JButton                     btOk             = GUIUtilities.createOkButton();

  private String              intro;
  private String              message;

  /** */
  public static final String  TITLE_DEFAULT    = JNPadBundle.getString("ExceptionDialog.title");   //$NON-NLS-1$
  /** */
  public static final String  INTRO_DEFAULT    = JNPadBundle.getString("ExceptionDialog.intro");   //$NON-NLS-1$

  /** Logger */
  private final static Logger LOGGER           = Logger.getLogger(ExceptionDialog.class.getName());

  /** UID */
  private static final long   serialVersionUID = 7269698195907364339L;

  /**
   * Instantiates a new exception dialog.
   *
   * @param w the w
   * @param e the e
   * @throws HeadlessException the headless exception
   */
  public ExceptionDialog(Window w, Throwable e) throws HeadlessException {
    this(w, TITLE_DEFAULT, INTRO_DEFAULT, formatException(e, false));
  }

  /**
   * Instantiates a new exception dialog.
   *
   * @param w the w
   * @param intro the intro
   * @param e the e
   * @throws HeadlessException the headless exception
   */
  public ExceptionDialog(Window w, String intro, Throwable e) throws HeadlessException {
    this(w, TITLE_DEFAULT, intro, formatException(e, false));
  }

  /**
   * Instantiates a new exception dialog.
   *
   * @param w the w
   * @param intro the intro
   * @param e the e
   * @param highlightCause the highlight cause
   * @throws HeadlessException the headless exception
   */
  public ExceptionDialog(Window w, String intro, Throwable e, boolean highlightCause) throws HeadlessException {
    this(w, TITLE_DEFAULT, intro, formatException(e, highlightCause));
  }

  /**
   * Instantiates a new exception dialog.
   *
   * @param w the w
   * @param title the title
   * @param intro the intro
   * @param e the e
   * @param highlightCause the highlight cause
   * @throws HeadlessException the headless exception
   */
  public ExceptionDialog(Window w, String title, String intro, Throwable e, boolean highlightCause) throws HeadlessException {
    this(w, title, intro, formatException(e, highlightCause));
  }

  /**
   * Instantiates a new exception dialog.
   *
   * @param w the w
   * @param title the title
   * @param intro the intro
   * @param message the message
   * @throws HeadlessException the headless exception
   */
  public ExceptionDialog(Window w, String title, String intro, String message) throws HeadlessException {
    this(w, title, intro, message, true);
  }

  /**
   * Instantiates a new exception dialog.
   *
   * @param w the w
   * @param title the title
   * @param intro the intro
   * @param message the message
   * @param modal the modal
   * @throws HeadlessException the headless exception
   */
  public ExceptionDialog(Window w, String title, String intro, String message, boolean modal) throws HeadlessException {
    super(w, title);
    try {
      this.intro = intro;
      this.message = message;
      
      jbInit();
      pack();
 
      Dimension size = getPreferredSize();
      Dimension sSize = GUIUtilities.getScreenDimension();
      Dimension max = new Dimension(sSize.width * 7 / 8, sSize.height * 7 / 8);
      setSize(GUIUtilities.getSize(size, max));
      setLocationRelativeTo(w);
      setModal(modal);
      setVisible(true);
    }
    catch(Exception ex) {
      LOGGER.log(Level.WARNING, ex.getMessage(), ex);
    }
  }

  /**
   * Component initialization.
   *
   * @throws Exception the exception
   */
  private void jbInit() throws Exception {
    contentPane = (JPanel)super.getContentPane();
    contentPane.setLayout(new BorderLayout());
    contentPane.add(lbIntro, BorderLayout.NORTH);
    contentPane.add(scrollPane, BorderLayout.CENTER);
    contentPane.add(pnButtons, BorderLayout.SOUTH);

    lbIntro.setText(intro);
    lbIntro.setToolTipText(intro);
    lbIntro.setBorder(GUIUtilities.createEmptyBorder(5));

    editorPane.setContentType("text/html"); //$NON-NLS-1$
    editorPane.setEditable(false);
    editorPane.addHyperlinkListener(new HyperlinkListener() {
      @Override
      public void hyperlinkUpdate(final HyperlinkEvent e) {
        if (e.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED))
          try {
            GUIUtilities.openBrowser(e.getURL());
          }
          catch (Exception ex) {
            LOGGER.log(Level.WARNING, ex.getMessage(), ex);
          }
      }
    });
    editorPane.setText(message.replaceAll(Utilities.LF_STRING, "<p>")); //$NON-NLS-1$
    editorPane.setCaretPosition(0);
    editorPane.setPreferredSize(new Dimension(500, 200));
    scrollPane.getViewport().add(editorPane, null);

    btOk.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(final ActionEvent e) {
        dispose();
      }
    });

    pnButtons.setLayout(new FlowLayout(FlowLayout.RIGHT));
    pnButtons.add(btOk);

    setDefaultCloseOperation(DISPOSE_ON_CLOSE);
  }

  /**
   * Escape pressed.
   */
  @Override
  protected void escapePressed() {
    dispose();
  }
  
  /**
   * Format exception.
   *
   * @param e Throwable
   * @param highlightCause boolean
   * @return String
   */
  public static String formatException(Throwable e, boolean highlightCause) {
    StringWriter sw = new StringWriter();
    PrintWriter pw = new PrintWriter(sw);
    if (highlightCause && e.getCause() != null) {
      pw.print(JNPadBundle.getString("ExceptionDialog.exception1") + Utilities.now()); //$NON-NLS-1$
      pw.print(JNPadBundle.getString("ExceptionDialog.exception2")); //$NON-NLS-1$
      e.getCause().printStackTrace(pw);
      pw.print(JNPadBundle.getString("ExceptionDialog.exception3")); //$NON-NLS-1$
    }
    e.printStackTrace(pw);
    return sw.toString();
  }

} // fin de ExceptionDialog
