// (c) MIT 2003.  All rights reserved.

////////////////////////////////////////////////////////////////////////////////
//
// FILE:	RecFrame.java
//
// AUTHOR:      Manoj D. Muzumdar
//              archon@ai.mit.edu
//
//              Adapted from code written by Luke Weisman
//              luke@ai.mit.edu
//
// DATE:        Jun 98
//
// COPYRIGHT:	Massachusetts Institute of Technology
//		All rights reserved.
//
// PURPOSE:     User interface component for drawing recognition
//
// HISTORY:     Mar 99 archon
//              Changed sizing to fit screens properly.
//
///////////////////////////////////////////////////////////////////////////////

package rec.ui;

import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import rec.sys.*;
import rec.geo.GPoint;
import rec.util.*;
import edu.mit.sketch.util.LoadStoreModule; import edu.mit.sketch.toolkit.StrokeData;
import edu.mit.sketch.toolkit.StrokeReader;
import edu.mit.sketch.toolkit.StrokeWriter;
import edu.mit.sketch.geom.Point;
import java.io.File;
import java.io.IOException;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Component;


public class RecFrame extends JFrame
{
  private Screen m_Screen;
  private JPanel m_Panel;
  private JPanel m_ButtonBar;
  private JMenuBar m_menuBar;

  private SpeechLabel m_speechLabel;
  private boolean m_speechActive = false;
  
  public RecFrame()  
  {
    this( "Recognizer System" );
  }

  public RecFrame( String name )
  {
    this( name, -1, -1 );
  }

  public RecFrame( int xsize, int ysize )
  {
    this( "Recognizer System", xsize, ysize );
  }

  public RecFrame( String name, int xsize, int ysize )
  { 
    setTitle( name );

    //    setSize( xsize, ysize + 40 );

    Container contentPane = getContentPane();
    contentPane.setLayout( new BorderLayout() );
    
    JButton undoButton = new JButton( "UNDO" );
    undoButton.setActionCommand( "UNDO" );

    undoButton.addActionListener( new ActionListener() {
      public void actionPerformed( ActionEvent ae )
	{
	  if( ae.getActionCommand().equals( "UNDO" ) )
	    m_Screen.getSurface().undo();
	}
    } );

    JButton redoButton = new JButton( "REDO" );
    redoButton.setActionCommand( "REDO" );

    redoButton.addActionListener( new ActionListener() {
      public void actionPerformed( ActionEvent ae )
	{
	  if( ae.getActionCommand().equals( "REDO" ) )
	    m_Screen.getSurface().redo();
	}
    } );

    JButton littleUndoButton = new JButton( "LITTLE UNDO" );
    littleUndoButton.setActionCommand( "LUNDO" );

    littleUndoButton.addActionListener( new ActionListener() {
      public void actionPerformed( ActionEvent ae )
	{
	  if( ae.getActionCommand().equals( "LUNDO" ) )
	    m_Screen.getSurface().littleUndo();
	}
    } );

    JButton littleRedoButton = new JButton( "LITTLE REDO" );
    littleRedoButton.setActionCommand( "LREDO" );

    littleRedoButton.addActionListener( new ActionListener() {
      public void actionPerformed( ActionEvent ae )
	{
	  if( ae.getActionCommand().equals( "LREDO" ) )
	    m_Screen.getSurface().littleRedo();
	}
    } );

    JButton debugButton = new JButton( "DEBUG" );
    debugButton.setActionCommand( "DEBUG" );

    debugButton.addActionListener( new ActionListener() {
      public void actionPerformed( ActionEvent ae )
	{
	  if( ae.getActionCommand().equals( "DEBUG" ) ) {
	    m_Screen.getSurface().recorder().printUndo();
	    m_Screen.getSurface().printWidgetPools();
	    m_Screen.getSurface().graphTimeInfo();
	    m_Screen.getSurface().printCurrentWidgetFamily();
	  }
	}
    } );

    JButton retryButton = new JButton( "TRY AGAIN" );
    retryButton.setActionCommand( "RETRY" );

    retryButton.addActionListener( new ActionListener() {
      public void actionPerformed( ActionEvent ae )
	{
	  if ( ae.getActionCommand().equals( "RETRY" ) ) {
	    m_Screen.getSurface().retry();
	  }
	}
    } );

    JButton drawMode = new JButton( "Drawing Mode" );
    drawMode.addActionListener( new ActionListener() {
	public void actionPerformed( ActionEvent ae )
	{
	  Surface s = m_Screen.getSurface();
	  boolean isShown = s.isWidgetSquiggleShown();
	  s.setIsWidgetSquiggleShown( !isShown );
	  repaint();
	}
      } );


    // button to save strokes
    JButton saveButton = new JButton( "Save" );
    saveButton.setActionCommand( "SAVE" );

    saveButton.addActionListener( new ActionListener() {
      public void actionPerformed( ActionEvent ae )
	{
	  if( ae.getActionCommand().equals( "SAVE" ) ) {
	    Surface s = m_Screen.getSurface();
	    Iterator widgets = s.getWidgetsIterator();
	    ArrayList<StrokeData> strokes = new ArrayList<StrokeData>();
	    
	    while (widgets.hasNext())
	    {
        Widget w = (Widget)widgets.next();
        if (w instanceof Squiggle) {
          // got a squiggle
          Squiggle sq = (Squiggle) w;
          strokes.add(sq.getStrokeData());
        }
	    }
      StrokeWriter.promptSaveStrokes(RecFrame.this, null, strokes);
      
	    // saving data in data.txt
      //    LoadStoreModule.storeRawVerticesInFile("data.txt", v);
	  }
	}
    } );

    // button to load strokes
    JButton loadButton = new JButton( "Load" );
    loadButton.setActionCommand( "LOAD" );

    loadButton.addActionListener( new ActionListener() {
        public void actionPerformed( ActionEvent ae ) {
	  if( ae.getActionCommand().equals( "LOAD" ) ) {
            Surface surface = m_Screen.getSurface();

            List strokes = null;
            try {
              strokes = StrokeReader.promptLoadStrokes(RecFrame.this);
            } catch(Exception e) {
              System.out.println("File not found");
              Assert.error( "File not found" );
            }
            
            Iterator it = strokes.iterator();
            while( it.hasNext() ) {
              StrokeData stroke = (StrokeData)it.next();
              Point[] points = stroke.vertices;
              surface.beginSquiggle(new GPoint(points[0].x, points[0].y),
                                    points[0].getTimeStamp());
              for( int i = 1; i < points.length; i++ ) {
                surface.addSquigglePoint(new GPoint(points[i].x,
                                                    points[i].y),
                                         points[i].getTimeStamp());
              }
              surface.endSquiggle( );
            }
          }
        }
      });

    m_Panel = new JPanel();
    m_Panel.setBorder( BorderFactory.createEtchedBorder() );
    m_Panel.setLayout(new FlowLayout(FlowLayout.CENTER));
    //m_Panel.add( undoButton );
    //m_Panel.add( littleUndoButton );
    m_Panel.add( retryButton );
    //    m_Panel.add( debugButton );
    m_Panel.add( drawMode );
    m_Panel.add( loadButton);
    //m_Panel.add( littleRedoButton );
    //m_Panel.add( redoButton );
    m_Panel.add(saveButton);    

    // archon:
    //
    // Create the screen last to get the proper dimensions of the panel.
    //
    // NOTE: Actually m_Panel.getSize().height returns 0 so approximate at 31
    //         pixels.  This works for 800x600 on Solaris 2.6.
    //
    // Make sure that the entire frame (buttons and all) can fit on
    //   a standard screen (800x600 by default).
    //
    if( xsize > 0 && ysize > 31 )
      m_Screen = new Screen( xsize, ysize - 31 );
    else
      m_Screen = new Screen( 800, 569 );

    //    setSize( m_Screen.getWidth(), m_Screen.getHeight() + m_Panel.getHeight() );
    //    setSize(xsize, ysize);

    Box southPanel = Box.createVerticalBox();
    m_ButtonBar  = new JPanel();
    m_ButtonBar.setLayout(new BorderLayout());
    m_ButtonBar.add(BorderLayout.CENTER, m_Panel);
    m_Panel.setBackground( new Color( 0, 102, 153 ) );
    southPanel.add( m_ButtonBar );
    southPanel.add( getLogo() );
    
    contentPane.add( BorderLayout.CENTER, m_Screen );
    contentPane.add( BorderLayout.SOUTH, southPanel );
    setIconImage( ClassFinder.getIcon( "AILabIcon.gif" ).getImage() );
  }

  /////////////////////////////////////////////////////////////////////////////

  private Component getSpeechLabel()
  {
    m_speechLabel = new SpeechLabel();
    
    JPanel panel = new JPanel();
    panel.setLayout( new BorderLayout() );
    panel.setBackground(  new Color( 0, 102, 153 ));
    //panel.setPreferredSize(new Dimension(36, 36));
    panel.setBorder( BorderFactory.createMatteBorder(5,5,5,5,new Color( 0, 102, 153 ) ));
    panel.add( m_speechLabel, BorderLayout.CENTER );
    
    return panel;
  }
  
  private Component getLogo()
  {
    ImageIcon icon = ClassFinder.getIcon( "DRG-banner.png" );
    JLabel logo = new JLabel( icon );
    JPanel panel = new JPanel();
    panel.setLayout( new BorderLayout() );
    panel.setBackground( Color.lightGray );
    panel.add( logo, BorderLayout.CENTER );
    return panel;
  }

  /**
   * turns on speech recognizer
   */
  public void activateSpeech() {
    m_speechActive = true;
  }
  
  /**
   * Receives new speech from the speech recognizer. Alerts the user
   * and allows them to see the text. If speech is not activated, does
   * nothing.
   */
  public void newSpeech(String speech) {
    if (m_speechActive) {
      m_speechLabel.addSpeech(speech);
    }
  }
 
  public void addSpeechIcon()
  {
    m_ButtonBar.add( BorderLayout.WEST, getSpeechLabel());
  }
  
  public void addButton( String buttonName, SurfaceMutator sm )
  {
    Assert.check( sm != null, "null surface mutator" );

    final String name = buttonName;
    final SurfaceMutator mutator = sm;

    JButton b = new JButton( name );
    b.setActionCommand( name );

    b.addActionListener( new ActionListener() {
      public void actionPerformed( ActionEvent ae )
	{
	  if( ae.getActionCommand().equals( name ) ) {

	    Surface s = m_Screen.getSurface();

	    m_SurfaceMutator.mutateSurface( s );

	    s.getScreen().repaint();
	  }
	}

      public final SurfaceMutator m_SurfaceMutator = mutator;
    } );

    m_Panel.add( b );
  }

  public void addToolbarComponent(Component c)
  {
    m_Panel.add(c);
    m_Panel.validate();
  }

  public void addMenuItem( String menuName, JMenuItem menuItem )
  {
    //Create the menu bar.
    if( m_menuBar == null ) {
      m_menuBar = new JMenuBar();
      setJMenuBar( m_menuBar );
    }
    JMenu menu = findMenu( menuName );
    if( menu == null ) {
      menu = new JMenu( menuName );
      m_menuBar.add( menu );
    }
    menu.add( menuItem );
  }

  private JMenu findMenu( String menuName )
  {
    for( int i = 0; i < m_menuBar.getMenuCount(); i++ ) {
      JMenu menu = m_menuBar.getMenu( i );
      if( menu != null && menu.getText().equals( menuName ) ) {
	return menu;
      }
    }
    return null;
  }

  /////////////////////////////////////////////////////////////////////////////

  public Screen getScreen()
  {
    return( m_Screen );
  }

  public void repaint( )
  {
    super.repaint();
    m_Screen.repaint();
  }


}


