// -*- c++ -*-

/*
 * 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: System.h,v 1.30 2003/09/13 08:46:07 florian Exp $
 */

#ifndef INCLUDE_JAKELIB2_LANG_SYSTEM_H
# define INCLUDE_JAKELIB2_LANG_SYSTEM_H
# include "../io/PrintWriter.h"
# include "../io/File.h"

namespace jakelib {
  namespace io {
    class File;
  }
  namespace util {
    class Properties;
  }

  namespace lang {
    /**
     * This class contains only static members that provide and
     * system-independend way to access system-specific properties
     * and functions.
     *
     * @class System
     * @version $Id: System.h,v 1.30 2003/09/13 08:46:07 florian Exp $
     * @author Florian 'Overflo' Wolff (florian@donuz.de)
     */
    class System : public Object
      {
      public:

        /**
         * Returns the current time in milliseconds since January, 1st 1970.
         * Note that the granularity of this value depends on the operation
         * system.
         */
	static jlong currentTimeMillis();

        /**
         * Returns the current value of the specified environment
         * variable.
         */
        static String* getEnv(const char* name);

        /**
         * Returns the current value of the specified environment
         * variable.
         */
        static String* getEnv(String* name);

        /** The system's End-Of-Line character sequence.
            Depends on the operating system. */
        static String* eol;

        /** A PrintWriter for the stdout stream. */
        static jakelib::io::PrintWriter *out;

        /** A PrintWriter for the stderr stream. */
        static jakelib::io::PrintWriter *err;

        /**
         * Initializes the random number generator.
         * \c currentTimeMillis() is used as the seed value.
         * Under Unix the current PID is added to this value.
         */
        static void randomize();

        /**
         * Returns the next random number \c >=0 and \c < \a max.
         *
         * @see #randomize()
         */
        static int random(int max);

        /**
         * @brief Called by \c Object::initJakelib2().
         * Do not use otherwise.
         */
        static void initSystemClass(int argc, char* argv[]);

        /**
         * Get a single system property by name.
         *
         * @param key The name of the system property to get.
         * @param def The default value (can be \c null).
         * @return the property, or \c def if not found.
         * @throws NullPointerException if key is \c null.
         * @throws IllegalArgumentException if key is \c "".
         */
        static String* getProperty(String *key, String *def = null);

        /**
         * Set all the system properties at once.
         *
         * @param props the new set of system properties
         */
        static void setProperties(jakelib::util::Properties *props);

        /**
         * Get all the system properties at once.
         * The required properties include:
         *
         * \li \c os.name              Operating System Name
         * \li \c os.arch              Operating System Architecture
         * \li \c os.version           Operating System Version
         * \li \c file.separator       File separator ("/" on Unix)
         * \li \c path.separator       Path separator (":" on Unix)
         * \li \c line.separator       Line separator ("\\n" on Unix)
         * \li \c user.name            User account name
         * \li \c user.home            User home directory
         * \li \c user.dir             User's current working directory
         *
         * @return The system properties, will never be \c null.
         */
        static jakelib::util::Properties* getProperties();

        /**
         * The running executable file.
         *
         * Taken from the \c argv[0] argument of the \c main() function.
         */
        static jakelib::io::File *file;

        /**
         * Returns a human-readable description of the system-dependend
         * error code given.
         */
        static jakelib::lang::String* explainErrorCode(jint code);

        /**
         * <b>DONT'T USE THIS!</b> Completely untested!
         *
         * Copy one array onto another from <code>src[srcStart]</code> ...
         * <code>src[srcStart+len-1]</code> to <code>dest[destStart]</code> ...
         * <code>dest[destStart+len-1]</code>. First, the arguments are validated:
         * neither array may be null, they must be of compatible types, and the
         * start and length must fit within both arrays. Then the copying starts,
         * and proceeds through increasing slots.  
         *
         * @param src the array to copy elements from
         * @param srcStart the starting position in src
         * @param dest the array to copy elements to
         * @param destStart the starting position in dest
         * @param len the number of elements to copy
         * @throws NullPointerException if src or dest is null
         * @throws ArrayStoreException if src or dest is not an array, if they are
         *         not compatible array types, or if an incompatible runtime type
         *         is stored in dest
         * @throws IndexOutOfBoundsException if len is negative, or if the start or
         *         end copy position in either array is out of bounds
         */
        /*+++AlFa 01/29/2003 FIXME arraycopy is a temporary solution
          It is only my best guess at the moment that 
          parent class for all arrays would be 'Objects'*/
        static void arraycopy(jakelib::lang::Array* src, jint srcStart,
                              jakelib::lang::Array* dest, jint destStart, jint len);
      
        /*         JAKELIB2_DECLARE_SYSTEM_ARRAYCOPY(jbyte); */
        /*         JAKELIB2_DECLARE_SYSTEM_ARRAYCOPY(jint); */
        /*         JAKELIB2_DECLARE_SYSTEM_ARRAYCOPY(jlong); */
        /*         JAKELIB2_DECLARE_SYSTEM_ARRAYCOPY(jdouble); */
        /*         JAKELIB2_DECLARE_SYSTEM_ARRAYCOPY(jfloat); */
        /*         JAKELIB2_DECLARE_SYSTEM_ARRAYCOPY(jchar); */
        /*         JAKELIB2_DECLARE_SYSTEM_ARRAYCOPY(jboolean); */

        //FIXME these are just 'quick & dirty' temporary solution
        /*         JAKELIB2_DECLARE_SYSTEM_ARRAYCOPYS(jbyte); */
        /*         JAKELIB2_DECLARE_SYSTEM_ARRAYCOPYS(jint); */
        /*         JAKELIB2_DECLARE_SYSTEM_ARRAYCOPYS(jlong); */
        /*         JAKELIB2_DECLARE_SYSTEM_ARRAYCOPYS(jdouble); */
        /*         JAKELIB2_DECLARE_SYSTEM_ARRAYCOPYS(jfloat); */
        /*         JAKELIB2_DECLARE_SYSTEM_ARRAYCOPYS(jchar); */
        /*         JAKELIB2_DECLARE_SYSTEM_ARRAYCOPYS(jboolean); */

      private:

        /** Stores the current system properties. This can be modified by
            \c setProperties(), but will never be \c null, because
            \c setProperties(null) sucks in the default properties. */
        static jakelib::util::Properties *properties;

        /** Stores the defaultproperties.. */
        static jakelib::util::Properties *defaultProperties;

        JAKELIB_DECLARE_CLASS(System);
      };
  }
}

#ifdef JAKELIB_DEBUG
# define JAKELIB_MSG(s) jakelib::lang::System::out->println(s)
#else
# define JAKELIB_MSG(s)
#endif

#endif

