package extensions.io;
import java.io.*;
import java.awt.*;
import extensions.lang.*;

/** Extend file to load and save String's while
  * encapsulating FileDialog.
  * @version 1.0.2
  * @author John Webster Small
  */
public class FileExtended extends File
{

  /** Default file name. */
  public static String Untitled = "Untitled";

  /** Is this the default file? */
  public boolean defaultFile = false;

  /** Constructs a FileExtended representing the
    * filed specified.
    * @param pathname the file path name
    * @exception NullPointerException If the file path
    *   is equal to null.
    */ 
  public FileExtended(String pathname) throws NullPointerException
    { super(pathname); }

  /** Constructs a FileExtended representing the
    * filed specified.
    * @param path the file's directory
    * @param name the file's name
    */ 
  public FileExtended(String path, String name)
    { super(path,name); }

  /** Constructs a FileExtended that represents the
    * file named Untitled in the current directory.
    * This is the default file.
    * @see #Untitled
    * @see #defaultFile
    */
  public FileExtended()
  {
    this(".",Untitled);
    defaultFile = true;
  }

  /** Constructs a FileExtended that represents the
    * file in the specified directory and name.
    * @param dir the directory represented by a File
    * @param name the name of the file in that directory
    */
  public FileExtended(File dir, String name)
    { super(dir,name); }

  /** Constructs a FileExtended that represents the
    * file specified by a File instance.  Note that
    * the pathname is converted to an absolute pathname.
    * @param pathname File representing the file
    */
  public FileExtended(File pathname)
    { this(pathname.getAbsolutePath()); }

  /** @return the path portion of the absolute pathname
    * @see java.io.File#getAbsolutePath
    */
  public String getAbsoluteParent()
  {
    String ap = getAbsolutePath();
    try  {
      return ap.substring(0,ap.lastIndexOf(getName())-1);
    } catch (Throwable t) {}
    return null;
  }

  /** Return FileExtended representing present working directory. */
  public static FileExtended pwd()
  {
    return new FileExtended((new FileExtended()).getAbsoluteParent());
  }

  /** If this FileExtended represents a file return
    * getAbsoluteParent() otherwise return
    * getAbsolutePath() minus any trailing ".".
    */
  public String getAbsolutePathDirectory()
  {
    String dir;
    if (isDirectory())  {
      dir = getAbsolutePath();
      try  {
        int i = dir.lastIndexOf(separator+".");
        if (i > 0)
          dir = dir.substring(0,i);
      } catch (Throwable t) {}
    }
    else
      dir = getAbsoluteParent();
    return dir;
  }

  /** Change current directory to one represent by this FileExtended. */
  public void cd()
  {
    try  {
      Runtime.getRuntime().exec("cd "+getAbsolutePathDirectory());
    } catch (Throwable t) {}
  }

  /** Prompt the user to accept, modify, or cancel the
    * file requested.
    * @param parent parent frame of FileDialog
    * @param title the FileDialog's title
    * @param mode the FileDialog's mode
    * @return Returns this FileExtended if accepted by
    *   the user.  If modified by the user a new FileExtended
    *   is returned representing the file specified by the
    *   user.  If the user clicks "cancel" null is returned.
    */
  public FileExtended fileDialog
    (Frame parent, String title, int mode)
  {
    FileDialog fd = new FileDialog(parent,title,mode);
    fd.setDirectory(getAbsolutePathDirectory());
    fd.setFile(getName());
    fd.show();
    String fn = fd.getFile();
    if (fn != null && fn.length() > 0)
      return new FileExtended(fd.getDirectory()+fn);
    return null;
  }

  /** Return file contents in a String instance.
    * @return contents of file
    * @exception IOException If any I/O errors occur
    *   the exception is thrown.
    */
  public String load() throws IOException
  {
    int size = (int)length();
    int count = 0;
    FileInputStream in = new FileInputStream(this);
    byte[] contents = new byte[size];
    while (count < size)
      count += in.read(contents,count,size-count);
    in.close();

    // Convert JDK 1.0.2 Windows platform bug: \r\n to \n
    // see save()
    for (int i = 1; i <= size; i++)
      if ((contents[i-1] == (byte) 13)
          && (contents[i] == (byte) 10))  {
        System.arraycopy(contents,i,contents,i-1,size-i);
        size--;
        contents[i-1] = (byte) '\n';
      }
    byte[] tmp = new byte[size];
    System.arraycopy(contents,0,tmp,0,size);
    return new String(tmp,0);
 

//    return new String(contents,0);  // JDK 1.0.2 way buggy
//    return new String(contents);  // JDK 1.1 way
  }

  /** Save the string contents to the file.
    * @param contents text to be saved
    */
  public void save(String contents)
    throws IOException
  {
    FileOutputStream out = new FileOutputStream(getAbsolutePath());
//    JDK 1.1 way
//    out.write(contents.getBytes());
//    out.close();

/*
    // JKD 1.0.2 way but buggy
    int size = contents.length();
    byte[] data = new byte[size];
    contents.getBytes(0,size-1,data,0); // bug in JDK 1.0.2
    for (int i = 0; i < size; i++)
    out.write(data);
    out.close();
*/

    // JDK 1.0.2 fix
    char[] c = contents.toCharArray();
    int i, j;
    for (i = j= 0; i < c.length; i++)
      if (c[i] == '\n')
        j++;
    byte[] data = new byte[c.length+j];
    for (i = j = 0; i < c.length; i++, j++)
      if (c[i] == '\n'
        && (SystemProperties.os == SystemProperties.Win95
        || SystemProperties.os == SystemProperties.WinNT))  {
        // This is for Windows 95/NT platform
        data[j++] = (byte) 13;
        data[j] = (byte) 10;
      }
      else
        data[j] = (byte) c[i];
    out.write(data);
    out.close();
  }

  /** Save the string contents to the file.  Prompt
    * user for file spec via a FileDialog.
    * @param parent parent of file dialog
    * @param title title of file dialog
    * @param contents text to be saved
    * @return File spec of saved file. Return null if
    *   operation is canceled
    */
  public FileExtended save
   (Frame parent, String title, String contents)
    throws IOException
  {
    FileExtended fe = fileDialog(parent,title,FileDialog.SAVE);
    if (fe != null)
      fe.save(contents);
    return fe;
  }
}
