//----------------------------------------------------------------------------
//
// Module:      LocalContext.java      
//
// Description: Keep context of a local file for FesiFTP
//
// FESI Copyright (c) Jean-Marc Lugrin, 2000
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//----------------------------------------------------------------------------

import java.io.*;

import com.oroinc.net.ftp.*;

import java.util.Date;
import java.util.Calendar;
import java.util.GregorianCalendar;

/**
 * Keep a local context for local file operations, similar to the FTP
 * context used for FTP operations.
 *<P>Note that the working directory is local to this object.
 */
public class LocalContext {
    
    // Current working directory File and name
    private String currentWorkingDirectoryName;
    private File currentWorkingDirectoryFile; 



    /**
     * Create a local context
     *
     * @exception   IOException  If local directory cannot be found
     */
    public LocalContext() throws IOException {
        super();
        currentWorkingDirectoryName = System.getProperty("user.dir", "");
        currentWorkingDirectoryFile = new File(currentWorkingDirectoryName);
        try {
            if (!currentWorkingDirectoryFile.isDirectory()) {
                throw new IOException("Not a directory name: " + currentWorkingDirectoryFile);
            }
        } catch (SecurityException e) {
            throw new IOException (e.toString());
        }
        currentWorkingDirectoryName = currentWorkingDirectoryFile.getCanonicalPath();
    }
    

    /**
     * Create a local context with a specific directory
     *
     * @param   localDirectory  working directory to use
     * @exception   IOException  If working directory invalid
     */
    public LocalContext(File localDirectory) throws IOException {
        super();
        currentWorkingDirectoryFile = new File(localDirectory.getCanonicalPath());
        try {
            if (!currentWorkingDirectoryFile.isDirectory()) {
                throw new IOException("Not a directory name: " + currentWorkingDirectoryFile);
            }
            currentWorkingDirectoryName = currentWorkingDirectoryFile.getCanonicalPath();
        } catch (SecurityException e) {
            throw new IOException (e.toString());
        }
    }


    /**
     * Get current working directory
     *
     * @return   Current working directory  
     */
    public String getCurrentWorkingDirectory() {
        return currentWorkingDirectoryName;
    }
    

    /**
     * Change current working directory to its parent
     *
     * @return  true if successful   
     * @exception   IOException  Not thrown
     */
    public boolean changeToParentDirectory() throws IOException {
        int ls = currentWorkingDirectoryName.lastIndexOf(File.separator);
        try {
            if (ls == -1) {
                return false;
            } else {
                String newDirectoryName = currentWorkingDirectoryName.substring(0,ls);
                // System.out.ln("NN: " + newDirectoryName);
                if (newDirectoryName.length()<=0) {
                    return false;
                } else {
                    File newDirectoryFile = new File(newDirectoryName);
                    if (newDirectoryFile.isDirectory()) {
                        currentWorkingDirectoryFile = newDirectoryFile;
                        currentWorkingDirectoryName = currentWorkingDirectoryFile.getCanonicalPath();
                    } else {
                        return false;
                    }
                }
            }
            return true;
        } catch (SecurityException e) {
            throw new IOException(e.toString());
        }
    }
        

    /**
     * Set to new working directory
     *
     * @param   newDirectoryName  New directory
     * @return  true if successful
     * @exception   IOException  not thrown
     */
    public boolean changeWorkingDirectory(String newDirectoryName) throws IOException {
        File newDirectoryFile;
        try {
            // Try relative
            newDirectoryFile = new File(currentWorkingDirectoryName, newDirectoryName);
            if (!newDirectoryFile.exists()) {          
                // Try absolute
                newDirectoryFile = new File(newDirectoryName);
            }
            if (newDirectoryFile.isDirectory()) {
                currentWorkingDirectoryFile = newDirectoryFile;
                currentWorkingDirectoryName = currentWorkingDirectoryFile.getCanonicalPath();
                return true;
            } else {
                return false;
            }
        } catch (SecurityException e) {
            throw new IOException(e.toString());
        }
    }
        
         

    /**
     * Get  listing of current directory content
     *
     * @return     An array of FTPFile describing the files
     * @exception   IOException  In case of error reading the directory
     */
    public FTPFile[] listFiles() throws IOException {
        String [] fileNames = currentWorkingDirectoryFile.list();
        FTPFile [] ftpFiles = new FTPFile[fileNames.length];
        try {
            for (int i=0; i<ftpFiles.length; i++) {
                String fileName = fileNames[i];
                String rawListing = "";
                File fileFile = new File(currentWorkingDirectoryFile,fileName);
                FTPFile fileInfo = new FTPFile();
                
                fileInfo.setType(fileFile.isDirectory() ? FTPFile.DIRECTORY_TYPE : 
                            (fileFile.isFile() ? FTPFile.FILE_TYPE : FTPFile.UNKNOWN_TYPE));
                rawListing += (fileFile.isDirectory() ? "d " : 
                            (fileFile.isFile() ? "f " : "u "));
                            
                if (fileFile.canRead()) {
                    fileInfo.setPermission(FTPFile.USER_ACCESS, FTPFile.READ_PERMISSION, true);
                    rawListing +="r"; 
                } else {
                    fileInfo.setPermission(FTPFile.USER_ACCESS, FTPFile.READ_PERMISSION, false);
                    rawListing +="-"; 
                }
                if (fileFile.canWrite()) {
                    fileInfo.setPermission(FTPFile.USER_ACCESS, FTPFile.WRITE_PERMISSION, true);
                    rawListing +="w"; 
                } else {
                    rawListing +="-"; 
                    fileInfo.setPermission(FTPFile.USER_ACCESS, FTPFile.WRITE_PERMISSION, false);
                }
                
                // Time is only a time stamp, not an absolute time.
                // It is not displayed but saved as if it was a java time
                // for possible use by macros 
                long timeStamp = fileFile.lastModified();
                Date date = new Date(timeStamp);
                Calendar cal = new GregorianCalendar();
                cal.setTime(date);
                fileInfo.setTimestamp(cal);
                // rawListing +=" " + date.toString();
                
                long fileLength = fileFile.length();
                String fileLengthString = Long.toString(fileLength);
                fileInfo.setSize(fileLength);
                int fileLengthSpace = 12 - fileLengthString.length();
                if (fileLengthSpace<=0) fileLengthSpace = 1;
                rawListing += ("             ").substring(13-fileLengthSpace) + fileLengthString;
                           
                fileInfo.setName(fileName);
                rawListing += " " + fileName;
                
                fileInfo.setRawListing(rawListing);
                ftpFiles[i] = fileInfo;
                // System.out.ln(i+": " + fileName + " - " + fileInfo);
            }
            return ftpFiles;
        } catch (SecurityException e) {
            throw new IOException(e.toString());
        }
    }
   

    /**
     * Create a new directory
     *
     * @param   newDirectoryName The name of the new directory  
     * @return     true if successful
     * @exception   IOException  in case of error creating the directory
     */
    public boolean makeDirectory(String newDirectoryName) throws IOException {
        try {
            File newDirectoryFile;
            // Make file name relative
            newDirectoryFile = new File(currentWorkingDirectoryName, newDirectoryName);
            return newDirectoryFile.mkdir();
        } catch (SecurityException e) {
            throw new IOException(e.toString());
        }
    }

    /**
     * Rename a file
     *
     * @param   srcFileName  The file to rename
     * @param   dstFileName  The new file name
     * @return  true if successful
     * @exception   IOException  in case of error renaming the file
     */
    public boolean renameFile(String srcFileName, String dstFileName) throws IOException {
        File file;
        try {
            // Try relative
            file = new File(currentWorkingDirectoryName, srcFileName);
            if (!file.exists()) {          
                // Try absolute
                file = new File(srcFileName);
            }
            // Try relative, then absolute
            boolean success = file.renameTo(new File(currentWorkingDirectoryName, dstFileName));
            if (!success) success = file.renameTo(new File(dstFileName)); 
            return success;
        } catch (SecurityException e) {
            throw new IOException(e.toString());
        }
    }

    /**
     * Delete a file
     *
     * @param   fileName  The file to delete
     * @return  true if successful
     * @exception   IOException  in case of error deleting the file
     */
    public boolean deleteFile(String fileName) throws IOException {
        File file;
        try {
            // Try relative
            file = new File(currentWorkingDirectoryName, fileName);
            if (!file.exists()) {          
                // Try absolute
                file = new File(fileName);
            }
            if (!file.isFile()) {
                throw new IOException(fileName + " is not a standard file");
            }
            return file.delete();
        } catch (SecurityException e) {
            throw new IOException(e.toString());
        }
    }
 

    /**
     * Delete a directory
     *
     * @param   dirName  The directory to delete
     * @return   true if success  
     * @exception   IOException  if the directory cannot be deleted
     */
    public boolean removeDirectory(String dirName) throws IOException {
        File file;
        try {
            // Try relative
            file = new File(currentWorkingDirectoryName, dirName);
            if (!file.exists()) {          
                // Try absolute
                file = new File(dirName);
            }
            if (!file.isDirectory()) {
                throw new IOException(dirName + " is not a directory");
            }
            return file.delete();
        } catch (SecurityException e) {
            throw new IOException(e.toString());
        }
    }
}