/* 
 *	Copyright (c) 1997-98 
 *	NorthEast Parallel Architectures Center, Syracuse University. 
 * All Rights Reserved. Permission to use, copy, modify, and distribute this
 * software and its documentation for educational, research and non-profit
 * purposes, without fee, and without a written agreement is hereby granted,
 * provided that the above copyright notice and this paragraph appear in all
 * copies. Permission to incorporate this software into commercial products may
 * be obtained by contacting the NorthEast Parallel Architectures Center. 
 *
 * The software program and documentation are supplied "as is",
 * without any accompanying services from NPAC. NPAC does not
 * warrant that the operation of the program will be uninterrupted or
 * error-free. The end-user understands that the program was developed for
 * research purposes and is advised not to rely exclusively on the program for
 * any reason.
 *
 */

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import java.net.*;

/*
 * An Emacs like TextEditor with Options to launch and edit multiple buffers
 * print, besides reular options to Search/Replace etc etc.
 *
 * @version     0.8 23rd April 1998
 * @author      Shrideep Pallickara
 *
 */
public synchronized class TextEditor extends Frame implements  KeyListener {
  
  ConsoleMenu consoleMenu;
  PopupMenu popup;
  /*Instance to hold the textarea*/
  TextArea textarea;
  private Color textColor, canvasColor; 
  private String fontName;
  private int fontSize;
  private int fontStyle;
  Graphics g;
  private Font textFont;
  Image _icon;
  static int bufferCount=0;
  Label statusInfo;
  String defaultStatus = new String("JDCE Text Editor Application (c)NPAC - Shrideep");
  Properties p = new Properties();
  
  public TextEditor() {
    
    consoleMenu = new ConsoleMenu(this);
    setMenuBar(consoleMenu);
    popup = new PopupMenu("Popup menu");
    popup.add(consoleMenu.fileMenu());
    popup.add(new MenuItem("-"));
    popup.add(consoleMenu.editMenu());
    popup.add(new MenuItem("-"));
    popup.add(consoleMenu.fontMenu());
    popup.add(consoleMenu.viewMenu());
    popup.add(new MenuItem("-"));
    popup.add(consoleMenu.searchMenu());
    popup.add(consoleMenu.colorMenu());
    popup.add(new MenuItem("-"));
    popup.add(consoleMenu.helpMenu());
    
    
    setLayout(new BorderLayout());
    add(statusInfo = new Label("", FlowLayout.CENTER), "South");
    statusInfo.setText(defaultStatus);
    
    textarea = new TextArea();
    textarea.setBackground(Color.white);
    textarea.requestFocus();
    add("Center",textarea);
    fontName="TimesRoman";
    fontSize=12;
    fontStyle = Font.PLAIN;
    textFont = new Font(fontName, fontStyle, fontSize);
    textarea.setFont(textFont);
    
    getImg("Palette.gif");
    add(popup);
    validate();
    setSize(450, 425);
    setVisible(true);
  }
  
  public void getImg(String name) {
    URL _iconURL;
    MediaTracker tracker = new MediaTracker(this);
    System.out.println("Trying for an Image");
    try {
      _iconURL = new URL("http://osprey7.npac.syr.edu:1998/iwt98/projects/book/servers/collaboration/demos/textEditor");
      _icon = Toolkit.getDefaultToolkit().getImage(_iconURL);
    } catch (Exception e) {
      _icon = Toolkit.getDefaultToolkit().getImage(name);
    }
    
    tracker.addImage(_icon,0);
    try { tracker.waitForID(0);
    } catch (InterruptedException e) {}
  }
  
  public void open() {
    Frame frame = new Frame();
    FileDialog fd = new FileDialog(frame, "Load Scribble", FileDialog.LOAD);
    fd.show();
    String filename = fd.getFile();
    File f = new File(filename);
    int size = (int)f.length();
    int bytes_read = 0;
    if (filename != null) {
      try {
	FileInputStream fis = new FileInputStream(filename);
	byte[] data = new byte[size];
	while (bytes_read < size) 
	  bytes_read += fis.read(data, bytes_read, size-bytes_read);
	textarea.setText(new String(data));
      }
      catch (Exception e) {
	System.out.println(e);
      }
    }
  }

  public void save() {
    Frame fr=new Frame();
    String FieldText;
    try {
      FileDialog fd = 
	new FileDialog(fr, "Choose filename to save as:", FileDialog.SAVE);
      if ((fr.getTitle()).equals("Untitled"))
	fd.setFile(fr.getTitle() + ".txt");
      else
	fd.setFile(fr.getTitle());
      fd.show();
      File fi = new File(fd.getDirectory(), fd.getFile());
      
      BufferedWriter bw = new BufferedWriter(new FileWriter(fi));
      FieldText = textarea.getText();
      bw.flush();
      bw.write(FieldText, 0, FieldText.length());
      bw.close();
      fr.setTitle(fi.getName());
    }
    catch (IOException e) {
      System.err.println(e);
    }
    catch (NullPointerException e) {
      //System.err.println("Error: " + e);
    }
  }

  public void loadSerialized() {
    Frame frame0 = new Frame();
    FileDialog fd = new FileDialog(frame0, "Load Serialized", FileDialog.LOAD);
    fd.show();
    String filename = fd.getFile();
    if (filename != null) {
      try {
	FileInputStream fiss = new FileInputStream(filename);
	ObjectInputStream oiss = new ObjectInputStream(fiss);
	String str = (String)oiss.readObject();
	textarea.setText(str);
      }
      catch (Exception e) {}
    }
  }

  /********************* METHODS TO DEAL WITH PRINTING *******************/

  public void printAll() {
    PrintJob pjob;
    try {
      SecurityManager sm = System.getSecurityManager();
      if (sm != null) sm.checkPrintJobAccess();
      pjob= Toolkit.getDefaultToolkit().getPrintJob(this, "text editor", p);
      if (pjob != null) {
	Graphics pg = pjob.getGraphics();
	if (pg != null) {
	  String s = textarea.getText();
	  printLongString (pjob, pg, s);
	  pg.dispose();
	}
	pjob.end();
      }
    } catch (SecurityException e) {
      System.err.println("Sorry. Printing is not allowed.");
    }
  }
  
  
  /* Print string to graphics via printjob
     Does not deal with word wrap or tabs */

  public void printLongString (PrintJob pjob, Graphics pg, String s) {
    int pageNum = 1;
    int linesForThisPage = 0;
    int linesForThisJob = 0;
    // Note: String is immutable so won't change while printing.
    if (!(pg instanceof PrintGraphics)) {
      throw new IllegalArgumentException ("Graphics context not PrintGraphics");
    }
    StringReader sr = new StringReader (s);
    LineNumberReader lnr = new LineNumberReader (sr);
    String nextLine;
    int pageHeight = pjob.getPageDimension().height;

    /*have to set the font to get any output */
    pg.setFont (textFont);
    FontMetrics fm = pg.getFontMetrics(textFont);
    int fontHeight = fm.getHeight();
    int fontDescent = fm.getDescent();
    int curHeight = 0;
    try {
      do {
        nextLine = lnr.readLine();
        if (nextLine != null) {         
          if ((curHeight + fontHeight) > pageHeight) {
            // New Page
            System.out.println ("" + linesForThisPage 
				+ " lines printed for page " + pageNum);
	    statusInfo.setText("" + linesForThisPage 
				+ " lines printed for page " + pageNum);
            pageNum++;
            linesForThisPage = 0;
            pg.dispose();
            pg = pjob.getGraphics();
            if (pg != null) {
              pg.setFont (textFont);
            }
            curHeight = 0;
          }
          curHeight += fontHeight;
          if (pg != null) {
            pg.drawString (nextLine, 0, curHeight - fontDescent);
            linesForThisPage++;
            linesForThisJob++;
          } else {
            System.out.println ("pg null");
          }
        }
      } while (nextLine != null);
    } catch (EOFException eof) {
      // Fine, ignore
    } catch (Throwable t) { // Anything else
      t.printStackTrace();
    }
    System.out.println ("" + linesForThisPage + 
			" lines printed for page " + pageNum);
    System.out.println ("pages printed: " + pageNum);
    System.out.println ("total lines printed: " + linesForThisJob);
  }




  /*******FUNCTIONS OPERATING ON THE TEXTAREA's ATTRIBUTES ***/

  public void setFontName(String fName) {
    String oldFontName= fontName;
    fontName = fName;
    textFont = new Font(fontName, fontStyle, fontSize);
    textarea.setFont(textFont);
  }
  
  public String getFontName() {
    return fontName;
  }
  
  /*Theres something you gotta remeber here,
    a) For plain styles ===>0
    b) for bold         ===>1
    c) for italics      ===>2
    d)for bold+italics  ===>3
    */
  
  public void setFontStyle(int fStyle) {
    int oldFontStyle = fontStyle;
    fontStyle = fStyle;
    textFont = new Font(fontName, fontStyle, fontSize);
    textarea.setFont(textFont);
  }
  
  public int getFontStyle() {
    return fontStyle;    
  }
  
  public void setFontSize(int fSize) {
    int oldFontSize = fontSize;
    fontSize = fSize;
    textFont = new Font(fontName, fontStyle, fontSize);
    textarea.setFont(textFont);    
  }

  public int getFontSize() {
    return fontSize;
  }

  /** The method which routes the relevant events to different methods **/
  
  public void performAction(String string) {
    if (string.equals("Browse"))
      open();
    if (string.equals("Save"))
      save();
    if (string.equals("LoadSer"))
      loadSerialized();
    if(string.equals("New")) System.out.println("Its works dude");
    if (string.equals("Exit"))
      System.exit(0);
    if (string.equals("Double size"))
      setSize(700, 600);
    if (string.equals("New Frame")) {
      new TextEditor();
      bufferCount++;
    }
    if ((string.equals("Delete Frame")) && (bufferCount!=0)) {
      this.dispose();bufferCount--;
    }
    if (string.equals("Print")) printAll();
  }
  
  public void keyPressed(KeyEvent keyEvent) {
  }
  
  public void keyReleased(KeyEvent keyEvent) {
  }
  
  public void keyTyped(KeyEvent keyEvent) {
    String string = "Undefined action";
    if (keyEvent.isControlDown())  {
      switch (keyEvent.getKeyChar() + 96) {
      case 97:
	string = "About";
	break;
	
      case 98:
	string = "Browse";
	break;
	
      case 99:
	string = "Copy";
	break;
	
      case 100:
	string = "Delete";
	break;
	
      case 101:
	string = "as new selection";
	break;
	
      case 102:
	string = "New Frame";
	break;

      case 104:
	string = "Help";
	break;
	
      case 108:
	string = "LoadSer";
	break;
	
      case 112:
	string = "Print";
	break;
	
      case 113:
	string = "Exit";
	break;
	
      case 114:
	string = "SaveSer";
	break;
	
      case 115:
	string = "Save";
	break;
	
      case 118:
	string = "as new image";
	break;
	
      case 119:
	string ="New";
	break;

      case 120:
	string = "Cut";
	break;
	
      case 122:
	string = "Undo";
	break;
      }
    }
    performAction(string);
  }
  
  public static void main(String astring[]) {
    TextEditor texteditor = new TextEditor();
    texteditor.setTitle("JDCE Text Editor");
  }
}