/*
 * Jakelib2 - General purpose C++ library
 * Copyright (C) 2001 Florian Wolff  (florian@donuz.de)
 *
 * This library 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.1 of the License, or (at your option) any later version.
 *
 * This library 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
 *
 * $Id: File.h,v 1.32 2003/08/18 15:51:52 florian Exp $
 */

#ifndef INCLUDE_JAKELIB2_IO_FILE_H
# define INCLUDE_JAKELIB2_IO_FILE_H

#if defined(HAVE_TIME_H) || defined(MSVC)
# include <time.h>
#endif

namespace jakelib {
  namespace util {
    class ArrayList;
  }

  namespace io {
    class FilenameFilter;
    class Files;

    /**
     * This class represents a file or directory on a local disk.
     *
     * It provides
     * facilities for dealing with a variety of systems that use various
     * types of path separators (\c "/" versus \c "\", for example). It also
     * contains methods useful for creating and deleting files and directories.
     *
     * @class File
     * @version $Id: File.h,v 1.32 2003/08/18 15:51:52 florian Exp $
     * @author Florian 'Overflo' Wolff (florian@donuz.de)
     */
    class File : public jakelib::lang::Object
      {
      public:

	File(jakelib::lang::String* pathname);
	File(char* pathname);

	jakelib::lang::String* getPath() { return path; }

	jakelib::lang::String* getDir() { return dir; }
	jakelib::lang::String* getFName() { return fname; }
	jakelib::lang::String* getName() { return name; }
	jakelib::lang::String* getExt() { return ext; }
	jakelib::lang::String* getLinkDest();

        /**
         * Returns an ArrayList containing the names of all Files in this
         * directory.
         *
         * @param filter An optinal FilenameFilter
         */
	jakelib::util::ArrayList* list(FilenameFilter *filter = null);
	jboolean isDirectory();
	jboolean isFile();
	jboolean isSystem();
	jboolean isHidden();
	jboolean isReadOnly();
	jboolean isLink();
	jlong length();
	time_t getModificationTime();
	time_t getAccessTime();
	void update();
	jboolean remove();

	/**
	 * @brief Creates the directory named by this abstract pathname.
	 *
	 * @return <tt>true</tt> if and only if the directory was created; <tt>false</tt> otherwise
	 */
	jboolean mkdir();
	jboolean mkdirs();
	static jakelib::lang::String* getTempDir();
	static File* createTempFile(char* prefix, char* suffix, char* directory);
	static File* createTempFile(char* prefix, char* suffix);
  
	static jakelib::lang::String *separator;
	static jakelib::lang::String *pathSeparator;
	static jakelib::lang::String *tempDir;
	static char separatorChar;
	static char pathSeparatorChar;

        static void initFileClass();
        static void init2FileClass();

        /**
         * @brief Returns a string representation (the path) of this \c File.
         */
        jakelib::lang::String* toString() { return path; };

        /**
         * Returns a canonical version of the given filename.
         * I.e. replace "\c \" by "\c /" on unices respectively
         * "\c /" by "\c \" on Windows.
         */
        static jakelib::lang::String* canonicalFilename(jakelib::lang::String *filename);

        /**
         * This method returns an array of filesystem roots. Some operating systems
         * have volume oriented filesystem. This method provides a mechanism for
         * determining which volumes exist. GNU systems use a single hierarchical
         * filesystem, so will have only one "\c /" filesystem root.
         *
         * @return An array of \c File objects for each filesystem root
         * available.
         */
        static Files* listRoots();

        /**
         * This method returns the path of this file as an absolute path name.
         * If the path name is already absolute, then it is returned. Otherwise
         * the value returned is the current directory plus the separator
         * string plus the path of the file.
         *
         * @return The absolute path of this file
         */
        virtual jakelib::lang::String* getAbsolutePath();

        /**
         * This method returns a canonical representation of the pathname of
         * this file. The actual form of the canonical representation is
         * different. On the GNU system, the canonical form differs from the
         * absolute form in that all relative file references to "." and ".."
         * are resolved and removed.
         *
         * Note that this method, unlike the other methods which return path
         * names, can throw an \c IOException. This is because native method 
         * might be required in order to resolve the canonical path
         *
         * @exception IOException If an error occurs
         */
        virtual jakelib::lang::String* getCanonicalPath();

        /**
         * This method returns true if this object represents an absolute file
         * path and false if it does not.  The definition of an absolute path varies
         * by system.  As an example, on GNU systems, a path is absolute if it starts
         * with a "/".
         *
         * @return \c true if this object represents an absolute file name,
         *         \c false otherwise.
         */
        virtual jboolean isAbsolute();

      private:

	long _length;
	jboolean _isFile;
	jboolean _isDirectory;
	jboolean _isSystem;
	jboolean _isHidden;
	jboolean _isReadOnly;
	jboolean _isLink;
	jboolean _linkDestRead;

	time_t _atime;
	time_t _mtime;

	jakelib::lang::String* dir;
	jakelib::lang::String* name;
	jakelib::lang::String* fname;
	jakelib::lang::String* ext;

        /** This is the path to the file set when the object is created. It
            may be an absolute or relative path name. */
	jakelib::lang::String* path;

	jakelib::lang::String* linkDest;

	void init(jakelib::lang::String* pathname);

      private:

#ifdef POSIX
        static Files* roots;
#endif

	JAKELIB_DECLARE_CLASS(File);
      };

    JAKELIB_DECLARE_ARRAY(File);
  }

  /** The maximum path length */
#define JAKELIB_MAX_PATH 500

}
#endif

