/*
 * Created on 21 Dec 2006 by Josef Garvi (www.edenfoundation.org)
 * Updated on 8 Dec 2009.
 */
package org.edenfoundation.swing;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.Dialog.ModalityType;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JEditorPane;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.border.EmptyBorder;

public class MsgDlg {

	public static void main(String args[]) {
		ArrayList<String> messages = new ArrayList<String>();

		messages
				.add("An <b>updated version</b> of this game named Railroad Tycoon Deluxe (RDX) was created and released in 1993. Despite a host of new features and graphics, RDX sold very poorly in stores, due to some bugs and slow gameplay (most notoriously the F4 map screen, which brings the game to a crawl).\r\n"
						+ "<BR><BR>"
						+ "RDX is essentially the same game as Railroad Tycoon, with improved hi-resolution graphics, new sound effects, and several additions. The additions are: new maps (South America and <b>Africa</b>) with region-specific cargo types (e.g. troops for Africa), new time ranges and locomotives, bandits who can hijack trains, and sheriffs who will arrest them.\r\n"
						+ "<BR><BR>"
						+ "Although the game is called Sid Meier's Railroad Tycoon Deluxe, Sid Meier himself had nothing to do with the development of this version.");
		messages
				.add("The original version allowed the player to start companies in <b>several settings:</b> <BR>the U.S. West and Midwest or the Northeast, England, and (on a smaller scale including southern England) Europe.");
		messages.add("Quick & Dirty.");
		messages.add("Two lines,\nno html.");
		messages
				.add("A sequel featuring improved graphics and more complex gameplay, Railroad Tycoon II, was published by Gathering of Developers in 1998 after PopTop Software acquired rights to the name.\r\n"
						+ "<UL><LI>"
						+ "Some features of the first version are missing in this sequel, such as the ability to build tunnels and signal towers, but many new possibilities were added, such as the ability to have unlimited money, trains, and train routes, much better control of routes, dozens of new maps, and the ability to create and modify scenarios and maps.</LI>"
						+ "<LI>"
						+ "The Dreamcast version was in full 3D.</LI>"
						+ "<LI>"
						+ "There are dozens of new scenarios to play including ones in Africa, North America, Germany, the Swiss Alps, the jungles of South America, and even several places around the world in a possible future where Earth's oceans have risen. Most of the ones in Railroad Tycoon 1 are in Railroad Tycoon 2. There are also many more first and second century campaigns to choose from than in Railroad Tycoon 1.</LI>"
						+ "<LI>"
						+ "An expansion pack, Railroad Tycoon II: Second Century, was later added which contained new scenarios focusing on modern and near-future times, plus added new elements to the economy. The game and its expansion were repackaged together in the Gold Edition and then, with 50 additional user-made scenarios, into the Platinum Edition.</LI>"
						+ "<LI>"
						+ "A short lived, budget title, named the Millennium Edition went on sale in 2000. It featured many scenarios and features of The Second Century, but no map editor. It had no instruction booklet and was sold only in a jewel case.</LI></UL>");

		int x = 0;
		for (String m : messages) {
			MsgDlg.question(null, m, JOptionPane.YES_NO_CANCEL_OPTION);
		}
		
		JOptionPane.showMessageDialog(null, "This message is very long, and the fact that it doesn't wrap by itself can probably make a user slighly frustrated. I mean, not everyone uses wide screens. Some people work on netbooks, and well, they are spared reading quite some boring stuff. :-) So perhaps it's a feature, not a bug?", "Message fit for Big Screens", JOptionPane.INFORMATION_MESSAGE);
	}

	private static JComponent wrap(String s) {
		return wrap(s, null);
	}

	private static int getContentHeight(String content, int width) {
		JEditorPane dummyEditorPane = new JEditorPane();
		dummyEditorPane.setSize(width, Short.MAX_VALUE);
		dummyEditorPane.setContentType("text/html");
		dummyEditorPane.setText(content);

		return dummyEditorPane.getPreferredSize().height;
	}

	private static JComponent wrap(String message, String shortTitle) {

		int maxWidth = 400;
		int maxHeight = Toolkit.getDefaultToolkit().getScreenSize().height * 2 / 3;

		String htmlizedMessage = null;
		if (message.contains("<p>") || message.contains("<P>")
				|| message.contains("<br>") || message.contains("<BR>")
				|| message.contains("<Br>"))
			htmlizedMessage = message;
		else
			htmlizedMessage = message.replace("\n", "<BR>");

		int h = getContentHeight(htmlizedMessage, maxWidth);

		JPanel pnl = new JPanel();
		pnl.setLayout(new BorderLayout());
		JEditorPane text = new JEditorPane("text/html", htmlizedMessage);
		text.setBorder(null);
		text.setBackground(null);
		text.setEditable(false);

		int titleHeight = 0;
		if (shortTitle != null) {
			JLabel lblTitle = new JLabel(shortTitle);
			lblTitle.setFont(lblTitle.getFont().deriveFont(
					lblTitle.getFont().getSize() * 1.5f));
			lblTitle.setBorder(new EmptyBorder(0, 0, 10, 0));
			lblTitle.setMaximumSize(lblTitle.getPreferredSize());
			titleHeight = lblTitle.getPreferredSize().height;
			pnl.add(lblTitle, BorderLayout.PAGE_START);
		}
		JScrollPane scroll = new JScrollPane(text);
		scroll.setBorder(null);
		scroll.setMaximumSize(new Dimension(maxWidth, maxHeight));
		scroll.setPreferredSize(new Dimension(Math.min(maxWidth, text
				.getPreferredSize().width), Math.min(maxHeight, getContentHeight(
				htmlizedMessage, maxWidth))));

		pnl.add(scroll, BorderLayout.CENTER);
		return pnl;
	}

	public static void error(Component owner, Throwable ex) {
		error(owner, ex, null);
	}

	public static void error(Component owner, Throwable ex, String title) {
		System.out.println("Error: " + ex.getMessage());
		ex.printStackTrace();
		if (ex.getMessage() == null)
			error(owner, ex.getClass().getName().substring(
					ex.getClass().getName().lastIndexOf('.') + 1), title);
		else
			error(owner, ex.getMessage(), title);
	}

	public static void error(Component owner, String message) {
		error(owner, message, null);
	}

	public static void error(Component owner, String message, String title) {
		JOptionPane.showMessageDialog(owner, wrap(message, "Error Encountered:"),
				title == null ? "Error" : title, JOptionPane.ERROR_MESSAGE);
	}

	public static void alert(Component owner, String message) {
		alert(owner, message, null);
	}

	public static void alert(Component owner, String message, String title) {
		JOptionPane.showMessageDialog(owner, wrap(message),
				title == null ? "Warning" : title, JOptionPane.WARNING_MESSAGE);
	}

	public static void information(Component owner, String message) {
		information(owner, message, null);
	}

	public static void information(Component owner, String message, String title) {
		JOptionPane.showMessageDialog(owner, wrap(message),
				title == null ? "Information" : title, JOptionPane.INFORMATION_MESSAGE);
	}

	public static void information(Component owner, Object[] messages) {
		generic(owner, JOptionPane.INFORMATION_MESSAGE, "Information", true,
				messages);
	}

	public static int question(Component owner, String message, int answerOptions) {
		return question(owner, message, null, answerOptions);
	}

	public static int question(Component owner, String message, String title, int answerOptions) {
		return JOptionPane.showConfirmDialog(owner, wrap(message),
				title == null ? "Question" : title, answerOptions, JOptionPane.QUESTION_MESSAGE);
	}

	public static void generic(Component owner, int messageType, String title,
			boolean modal, Object... messages) {
		JOptionPane optionPane = getNarrowOptionPane(50);
		Object[] msgParam = new Object[messages.length];
		for (int i = 0; i < messages.length; i++) {
			if (messages[i] instanceof String) {
				msgParam[i] = wrap((String) messages[i]);
			} else
				msgParam[i] = messages[i];
		}
		optionPane.setMessage(msgParam);
		optionPane.setMessageType(messageType);
		JDialog dialog = optionPane.createDialog(owner, title);
		dialog.setResizable(true);
		dialog.setTitle(title);
		if (!modal) {
			dialog.setModalityType(ModalityType.MODELESS);
			dialog.setAlwaysOnTop(true);
		}
		FrameExtra.centerOnWindow(FrameExtra.ancestorOfComponent(owner), dialog);
		dialog.setVisible(true);
	}

	private static JOptionPane getNarrowOptionPane(int maxCharactersPerLineCount) {
		// Our inner class definition
		class NarrowOptionPane extends JOptionPane {
			int maxCharactersPerLineCount;

			NarrowOptionPane(int maxCharactersPerLineCount) {
				this.maxCharactersPerLineCount = maxCharactersPerLineCount;
			}

			@Override
			public int getMaxCharactersPerLineCount() {
				return maxCharactersPerLineCount;
			}
		}

		return new NarrowOptionPane(maxCharactersPerLineCount);
	}

	public static void registerDefaultExceptionHandler() {
	   Thread.setDefaultUncaughtExceptionHandler(
	         new Thread.UncaughtExceptionHandler() {
	            public void uncaughtException(Thread t, Throwable e) {
	               error(null, e);
	            }
	         });
	}

}
