// ============================================================================
// File:               $File$
//
// Project:
//
// Purpose:
//
// Author:             Rammi
//
// Copyright Notice:   (c) 1999-2006  Rammi (rammi@caff.de)
//                     This code is in the public domain.
//                     Use at own risk.
//                     No guarantees given.
//
// Latest change:      $Date: 2006-02-01 13:48:49 +0100 (Mi, 01 Feb 2006) $
//
// History:	       $Log$
//=============================================================================

package de.caff.util.debug;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.io.FileWriter;
import java.util.*;


/**
 *  A text window frame in which debugging messages are outputted in cooked format.
 *  It is possible to show an extended interface with buttons allowing global tuning
 *  of the debugging interface.
 *  
 *  @see Debug
 *
 *  @author Rammi
 */
public class DebugMessageWindow
        extends JFrame
        implements CookedMessageDebugListener
{
  private JTextArea      _msgArea;
  private int            _endPos;

  
  /**
   *  Constructor.
   *  @param  extended  use extended interface with tuning buttons?
   */
  public DebugMessageWindow(boolean extended) {
    super("Debug Messages");

    setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
    _msgArea = new JTextArea(25, 100);
    _msgArea.setFont(new Font("Monospaced", Font.PLAIN, 12));
    _msgArea.setEditable(false);
    getContentPane().add(new JScrollPane(_msgArea));

    JPanel panel = new JPanel(new BorderLayout());
    getContentPane().add("East", panel);
      
    if (extended) {
      JPanel memPanel = new MemoryUsagePanel();
      memPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(),
							  "Memory"));
      panel.add("North", memPanel);

      JPanel switchPanel = new DebugLevelSwitchBoard();
      panel.add("Center", switchPanel);
      switchPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(),
							  "Global Settings"));
      panel.add(switchPanel);
    }

    JPanel allButtons  = new JPanel(new BorderLayout());
    allButtons.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
    panel.add("South", allButtons);

    JButton b = new JButton("Print System Properties");
    allButtons.add("North", b);
    b.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
	printProperties();
      }
    });
    b.setToolTipText("Print the system properties in the text window");
    
    JPanel buttonPanel = new JPanel(new GridLayout(0, 1));
    allButtons.add("South", buttonPanel);

    b = new JButton("Clear");
    buttonPanel.add(b);
    b.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
	clear();
      }
    });
    b.setToolTipText("Clears the text window");

    b = new JButton("Save...");
    buttonPanel.add(b);
    b.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
	save();
      }
    });
    b.setToolTipText("Allows to save the content of the text window");

    addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
	Debug.removeCookedMessageDebugListener(DebugMessageWindow.this);
	dispose();
      }
    });
    Debug.addCookedMessageDebugListener(this);

    pack();
    setVisible(true);
  }

  /**
   *  Receive a message and append it to the text window.
   *  @param  msgType  ignored
   *  @param  message  new message
   *  @param  pos      position
   */
  public void receiveCookedMessage(int msgType, final String message, final String pos) {
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
	append(message+DebugMessageCook.cookedPosition(pos));
      }
    });
  }

  /**
   *  Append a text to the message area.
   *  @param  text  text to append
   */
  private void append(String text) {
    _msgArea.append(text);
    _endPos += text.length();
    _msgArea.setCaretPosition(_endPos);
  }

  /**
   *  Clear text window.
   */
  private void clear() {
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
	_msgArea.setText("");
	_endPos = 0;
      }
    });
  }

  /**
   *  Save text window content.
   */
  private void save() {
    JFileChooser chooser = new JFileChooser();

    if (chooser.showDialog(this, "Sichern") == JFileChooser.APPROVE_OPTION) {
      File file = chooser.getSelectedFile();
      try {
	FileWriter out = new FileWriter(file);
	out.write(_msgArea.getText());
	out.close();
	Debug.message("Debugmeldungen gesichert in \"%1\"", file);
      } catch (Exception x) {
	Debug.error("Sichern von \"%1\" gescheitert.\nGrund:\n%2", 
		    file, x.getMessage());
      }
    }
  }

  /**
   *  Add the system properties to the debug window.
   */
  private void printProperties() {
    ArrayList<String> lines = new ArrayList<String>();
    for (Enumeration p = System.getProperties().propertyNames();  p.hasMoreElements();  ) {
      String prop = (String)p.nextElement();
      try {
	lines.add("\t"+prop+" = \""+System.getProperty(prop)+"\"\n");
      } catch (SecurityException x) {
	lines.add("\t"+prop+" not available due to security restrictions\n");
      }
    }
    Collections.sort(lines);
    
    append("SYSTEM PROPERTIES:\n");
    for (String line: lines) {
      append(line);
    }
  }
}




