package hirondelle.movies.exception;

import hirondelle.movies.util.Util;
import hirondelle.movies.util.ui.UiUtil;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.util.logging.Logger;
import javax.swing.JOptionPane;

/**
 Custom handler for uncaught exceptions.
 
 <P>By default, a Swing app will handle uncaught exceptions simply by printing a stack trace to 
 {@link System#err}. However, the end user sees nothing happen. 
  This class addresses that problem, by showing the end user a simple error message in a modal dialog.
  (The dialog's owner is the currently active frame.)
  
 <P>In JDK1.4, the simplest way of overriding the default handler for uncaught exceptions is  
 to use the following undocumented feature :
 <ul>
   <li>create a class with a no-argument constructor
   <li>add to it a method :<tt>public void handle(Throwable aThrowable){...}</tt>
   <li>upon startup, add a {@link System} property named <tt>'sun.awt.exception.handler'</tt>, 
   whose value is the fully qualified class name of this new handler class
   </ul> 
 
 The above technique is used by this class. 
 
 <P>Other alternative methods include :
 <ul>
   <li>create a custom {@link java.util.logging.Handler}, and attach it to your application's loggers
   <li>override {@link ThreadGroup#uncaughtException(java.lang.Thread, java.lang.Throwable)}
   <li>use later versions of Java, which provides an API related to this problem
  </ul> 
*/
public final class ExceptionHandler {

  /**
   No-argument constructor.
  This class must have a no-arg constructor (see class comment).
  */
  public ExceptionHandler(){
    //empty
  }
  
  /** 
   Custom handler for uncaught exceptions.
   
   <P>Displays a simple model dialog to the user, showing that an error has occured.  
   The text of the error includes {@link Throwable#toString()}.
  */
  public void handle(Throwable aThrowable){
    fLogger.severe(getStackTrace(aThrowable));
    JOptionPane.showMessageDialog(
      UiUtil.getActiveFrame(), "Error: " + aThrowable.toString(), 
      "Error", JOptionPane.ERROR_MESSAGE
    );
  }

  // PRIVATE //
  private static final Logger fLogger = Util.getLogger(ExceptionHandler.class);
  
  private String getStackTrace(Throwable aThrowable) {
    final Writer result = new StringWriter();
    final PrintWriter printWriter = new PrintWriter(result);
    aThrowable.printStackTrace(printWriter);
    return result.toString();
  }
}