package org.jcon.ui;

import org.jcon.df.edit.EditEvent;
import org.jcon.df.edit.EditListener;
import org.jcon.ui.VisualLib;
import org.jcon.ui.WindowLib;
import org.jcon.ui.WindowMgr;
import org.jcon.ui.WindowTitleBlinker;
import org.jcon.util.GenLib;
import java.awt.Window;
import java.awt.Dialog;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Cursor;
import java.awt.event.*;
import javax.swing.JWindow;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JDialog;

/**
 * This reusable class provides a window with configurable
 * properties. It is designed to be subclassed or used for
 * specific behavior, such as editing fields or a message box.
 * <P>
 * If no listener is provided then the window will dispose
 * of itself when a button is clicked or close window is
 * attempted. This is exactly what a typical "okay"
 * message box would want to do.
 *
 * @author Jack Harich
 */
public class PrimeWindow implements Runnable, ActionListener,
    WindowListener, KeyListener, java.io.Serializable {

//---------- Private Fields ------------------------------
private boolean isFrame = true;
private boolean isModal = true;
private String  title;
private String  windowClosingCommand = "CloseWindow";
private boolean revealInThread = false;
private boolean autoDispose = false;
private boolean escapeToClose = false;
private JPanel   mainPanel = new JPanel();
private ActionListener listener = this;
private KeyListener keylistener;

private boolean waiting;
private Cursor  normalCursor;
private WindowTitleBlinker blinker;

//---------- Protected Fields ----------------------------
protected Window         myWindow;

//---------- Initialization ------------------------------
public PrimeWindow() {
    mainPanel.setLayout(new BorderLayout());
    mainPanel.setBackground(Color.lightGray);
}
public void finalize() {
    closeWindow();
}
//---------- Runnable Interface --------------------------
/**
 * This method is for internal use.
 */
public void run() {
    myWindow.setVisible(true);
}
//---------- ActionListener Implementation ---------------
/**
 * This method is for internal use.
 *
 * @param ActionEvent evt - The ActionEvent.
 */
public void actionPerformed(ActionEvent evt) {
    // No listener provided
    closeRequested();
}
//---------- WindowListener Implementatons ---------------
/**
 * This method is used to detect the user attempting to
 * manually close the window directly. The other
 * windowXXX() methods have empty implementations.
 *
 * @param WindowEvent evt - The WindowEvent.
 */
public void windowClosing(WindowEvent evt) {
    // User clicked on X or chose window Close
    closeRequested();
}
/**
 * Empty implementation.
 */
public void windowClosed(WindowEvent evt) { }
/**
 * Empty implementation.
 */
public void windowDeiconified(WindowEvent evt) { }
/**
 * Empty implementation.
 */
public void windowIconified(WindowEvent evt) { }
/**
 * Empty implementation.
 */
public void windowOpened(WindowEvent evt) { }
/**
 * Empty implementation.
 */
public void windowActivated(WindowEvent evt) {  }
/**
 * Empty implementation.
 */
public void windowDeactivated(WindowEvent evt) { }

//---------- KeyListener Implementation ------------------
public void keyTyped(KeyEvent evt) {
  // print(" - keyTyped");
}
public void keyPressed(KeyEvent evt) {
    //  print(" - keyPressed " + evt);
    if(evt.getComponent() != myWindow.getFocusOwner()) {
        // For work in progress by Joshua
        //print(".keyPressed() - We got a fake event! skipping!");
        return;
    }
    if (evt.getKeyCode() == KeyEvent.VK_ESCAPE) {
        if (escapeToClose) closeRequested();
    }
    // Forward key pressed
    if (keylistener == null) {
        //print(".keyPressed() - no keyListener");
    } else {
        keylistener.keyPressed(evt);
    }
}
public void keyReleased(KeyEvent evt) {
    // print(" - keyReleased");
}

//---------- Properties ----------------------------------
//----- isFrame
/**
 * Sets the IsFrame property. If true then the window will
 * be a Frame, otherwise it's a Dialog. The default is a
 * Frame.
 */
public void setFrame(boolean isFrame) {
    this.isFrame = isFrame;
}
/**
 * Returns the IsFrame property.
 */
public boolean isFrame() {
    return isFrame;
}
//----- actionListener
/**
 * Sets the ActionListener property. This listener will be
 * notified of ActionEvents and WindowClosing attempts
 * unless null. If no listener is provided then any button
 * click or attempt to close the window by the user will
 * result in the window being disposed.
 *
 * @param ActionListener listener - The ActinListener property value.
 */
public void setActionListener(ActionListener listener) {
    this.listener = listener;
}
public void setKeyListener(KeyListener listener) {
    this.keylistener = listener;
}
public ActionListener getActionListener() {
    return listener;
}
//----- isModal
/**
 * Sets the Modal property. If the window is a Dialog then
 * the Modal property determines if it's modal. The default
 * is true.
 *
 * @param boolean isModal - The Modal property value.
 */
public void setModal(boolean isModal) {
    this.isModal = isModal;
}
public boolean isModal() {
    return isModal;
}
//----- title
/**
 * Sets the Title property, which will become the window's title.
 *
 * @param String title - The Title property value.
 */
public void setTitle(String title) {
    this.title = title;
    if (myWindow instanceof Frame) {
         ((Frame)myWindow).setTitle(title);
    } else if (myWindow instanceof Dialog) {
        ((Dialog)myWindow).setTitle(title);
    }
}
public String getTitle() {
    return title;
}
//----- visible
/**
 * Sets the Visible property. If visible and RevealInThread
 * are both true then a new thread is started to show the
 * window. Otherwise this behaves normally.
 */
public void setVisible(boolean visible) {
    if (visible && revealInThread) {
        Thread thread = new Thread(this);
        thread.setPriority(Thread.MAX_PRIORITY);
        thread.start();
    } else {
        //print(".setVisible() - before");
            myWindow.setVisible(visible);
        //print(".setVisible() - after");
    }
}
public boolean isVisible() {
    return myWindow.isVisible();
}
//----- revealInThread
/**
 * Sets the ShowInThread property. The default is false.
 */
public void setShowInThread(boolean showInThread) {
    this.revealInThread = showInThread;
}
public boolean isShowInThread() {
    return revealInThread;
}
//----- autoDispose
/**
 * Sets the AutoDispose property. If true and no listener
 * is provided then the window will be automatically
 * disposed when any button is clicked or the window is
 * closed directly. The default is false.
 */
public void setAutoDispose(boolean autoDispose) {
    this.autoDispose = autoDispose;
}
public boolean isAutoDispose() {
    return autoDispose;
}
//----- escapeToClose
/**
 * Sets the EscapeToClose property, which if true will
 * cause pressing the ESCAPE key to be the same as manually
 * closing the window. The default is false. Useful for
 * simple dialogs.
 */
public void setEscapeToClose(boolean escapeToClose) {
    this.escapeToClose = escapeToClose;
}
public boolean getEscapeToClose() {
    return escapeToClose;
}
//----- enabled
public void setEnabled(boolean enabled) {
    if (myWindow != null) myWindow.setEnabled(enabled);
}    
//----- waiting
// DO NOT USE - Causes Java 1.1.5 javai.dll page fault
// Reboot seemed to solve problem
public void setWaiting(boolean waiting) {
    if (true) return; // DISABLED
    if (this.waiting == waiting || myWindow == null) return;
    this.waiting = waiting;
    
    if (waiting) {
        print(".setWaiting() - Setting to true");
        myWindow.setEnabled(false); // Prevent extra events
        blinker = new WindowTitleBlinker();
        blinker.setWindow(myWindow);
        blinker.setStartDelay(0);
        blinker.setBlinkText(" ***");
        blinker.start();
    } else {
        print(".setWaiting() - Setting to false");
        blinker.stop();
        blinker = null;
        myWindow.setEnabled(true);
    }        
    // Also fails    
    /** if (waiting) {
        normalCursor = myWindow.getCursor();
        myWindow.setCursor(new Cursor(Cursor.WAIT_CURSOR));
        
    } else {
        myWindow.setCursor(normalCursor);
    } */
}   
//----- Other
/**
 * Returns the panel that contains the window's components.
 */
public JPanel getMainPanel() {
    return mainPanel;
}
/**
 * Returns the window. Useful for positioning, etc. Do NOT
 * cast to Frame or Dialog and manipulate directly.
 */
public Window getWindow() {
    return myWindow;
}
/**
 * Sets the WindowClosingCommand property. If the listener
 * is not null and a WindowClosing is received, an ActionEvent
 * with its action command set to the WindowClosingCommand's
 * value will be sent to the listener. The default value
 I is "CloseWindow".
 *
 * @param String command - The WindowClosingCommand property.
 */
public void setWindowClosingCommand(String command) {
    windowClosingCommand = command;
}
/**
 * Closes the window by disposing it.
 */
 public void dispose() {
    myWindow.dispose();
 }
//---------- Public Methods ------------------------------
/**
 * Disposes and releases the window. This should always be
 * called when done.
 */
public void closeWindow() {
    //print(".closeWindow() - Entered");
    if (myWindow != null) myWindow.dispose();
    myWindow = null;
}
/**
 * Initializes the window. This must be called AFTER adding
 * components and BEFORE packing or showing.
 */
public void initWindow() {

	// CMC - This now assumes isFrame implies isJFrame
    if (isFrame) {
        JFrame frame = WindowMgr.createRegisteredFrame();
        frame.setTitle(title);
        frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        myWindow = frame;
    } else {
        JDialog dialog = WindowMgr.createDialog(isModal);
        dialog.setTitle(title);
        dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
        myWindow = dialog;
    }
    myWindow.setBackground(Color.lightGray);

    if (myWindow instanceof JDialog) {
 	    ((JDialog)myWindow).getContentPane().add("Center", mainPanel);
    }
    else if (myWindow instanceof JFrame) {
    	((JFrame)myWindow).getContentPane().add("Center", mainPanel);
    }
    else {
    	myWindow.add("Center", mainPanel);
		GenLib.helpfulHint("Warning: " + getTitle() + " is an awt Frame or Dialog!");
    }
    myWindow.addWindowListener(this);
    if(myWindow instanceof JFrame) {
        VisualLib.addKeyListenerToAll(myWindow, this);
    }
}
/**
 * Packs the window.
 */
public void packWindow() {
    myWindow.pack();
}
/**
 * Centers the window.
 */
public void centerWindow() {
    WindowLib.center(myWindow);
}
//---------- Protected Methods ---------------------------
protected void closeRequested() {
    // listener == this if no listener provided
    if (listener == this) {
        if (autoDispose) {
            print(".closeRequested() - autoDispose = true, closing Window");
            closeWindow();
        }
    } else if (listener != null) {
        ActionEvent event = new ActionEvent(this,
            ActionEvent.ACTION_PERFORMED, windowClosingCommand);
        listener.actionPerformed(event);
    }
}
//---------- Private Methods -----------------------------
//--- Std
private static void print(String text) {
    System.out.println("PrimeWindow" + text);
}

} // End class
