// -*- 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: TimeZone.h,v 1.8 2003/09/03 12:01:08 florian Exp $
 */

#ifndef INCLUDE_JAKELIB2_UTIL_TIMEZONE_H
# define INCLUDE_JAKELIB2_UTIL_TIMEZONE_H

namespace jakelib {
  namespace util {
    class SimpleTimeZone;
    class Date;
    class Locale;
    class Hashtable;

    /**
     * This class represents a time zone offset and handles daylight savings.
     * 
     * You can get the default time zone with \c getDefault.
     * This represents the time zone where program is running.
     *
     * Another way to create a time zone is \c getTimeZone, where
     * you can give an identifier as parameter.  For instance, the identifier
     * of the Central European Time zone is "\c CET".
     *
     * With the \c getAvailableIDs method, you can get all the
     * supported time zone identifiers.
     *
     * @class TimeZone
     * @version $Id: TimeZone.h,v 1.8 2003/09/03 12:01:08 florian Exp $
     * @author Jochen Hoenicke
     * @author Florian 'Overflo' Wolff (florian@donuz.de)
     */
    class TimeZone : public jakelib::lang::Object
      {
      public:

        typedef enum {
          /** Constant used to indicate that a short timezone abbreviation should
              be returned, such as "EST". */
          SHORT,
          /** Constant used to indicate that a long timezone name should be
              returned, such as "Eastern Standard Time". */
          LONG
        } TIMEZONE_STYLE;

        /**
         * Gets the time zone offset, for current date, modified in case of 
         * daylight savings.  This is the offset to add to UTC to get the local
         * time.
         *
         * @param era the era of the given date
         * @param year the year of the given date
         * @param month the month of the given date, 0 for January.
         * @param day the day of month
         * @param dayOfWeek the day of week
         * @param milliseconds the millis in the day (in local standard time)
         * @return the time zone offset in milliseconds.
         */
	virtual int getOffset(int era, int year, int month, int day,
			      int dayOfWeek, int milliseconds) = 0;

        /**
         * Sets the time zone offset, ignoring daylight savings.  This is
         * the offset to add to UTC to get the local time.
         *
         * @param offsetMillis the time zone offset to GMT.
         */
	virtual void setRawOffset(int offsetMillis) = 0;

        /**
         * Gets the time zone offset, ignoring daylight savings.  This is
         * the offset to add to UTC to get the local time.
         *
         * @return the time zone offset in milliseconds.  
         */
	virtual int getRawOffset() = 0;

        /**
         * Gets the identifier of this time zone. For instance, PST for
         * Pacific Standard Time.
         *
         * @return the ID of this time zone.  
         */
	virtual jakelib::lang::String* getID();

        /**
         * Sets the identifier of this time zone. For instance, PST for
         * Pacific Standard Time.
         *
         * @param id the new time zone ID.
         */
	virtual void setID(jakelib::lang::String *id);

        /**
         * This method returns a string name of the time zone suitable
         * for displaying to the user.  The string returned will be the long
         * description of the timezone in the current locale.  The name
         * displayed will assume daylight savings time is not in effect.
         *
         * @return The name of the time zone.
         */
	virtual jakelib::lang::String* getDisplayName();

        /**
         * This method returns a string name of the time zone suitable
         * for displaying to the user.  The string returned will be the long
         * description of the timezone in the specified locale. The name
         * displayed will assume daylight savings time is not in effect.
         *
         * @param locale The locale for this timezone name.
         *
         * @return The name of the time zone.
         */
	virtual jakelib::lang::String* getDisplayName(Locale *locale);

        /**
         * This method returns a string name of the time zone suitable
         * for displaying to the user.  The string returned will be of the
         * specified type in the current locale. 
         *
         * @param daylight Whether or not daylight savings time is in effect.
         * @param style \c LONG for a long name, \c SHORT for
         * a short abbreviation.
         *
         * @return The name of the time zone.
         */
	virtual jakelib::lang::String* getDisplayName(jboolean daylight,
                                                      TIMEZONE_STYLE style);

        /**
         * This method returns a string name of the time zone suitable
         * for displaying to the user.  The string returned will be of the
         * specified type in the specified locale. 
         *
         * @param daylight Whether or not daylight savings time is in effect.
         * @param style \c LONG for a long name, \c SHORT for
         * a short abbreviation.
         * @param locale The locale for this timezone name.
         *
         * @return The name of the time zone.
         */
	virtual jakelib::lang::String* getDisplayName(jboolean daylight,
                                                      TIMEZONE_STYLE style,
                                                      Locale *locale);

        /** 
         * Returns true, if this time zone uses Daylight Savings Time.
         */
	virtual jboolean useDaylightTime() = 0;

        /**
         * Returns \c true, if the given date is in Daylight Savings Time in this
         * time zone.
         *
         * @param date the given Date.
         */
	virtual jboolean inDaylightTime(Date* date) = 0;

        /**
         * Gets the TimeZone for the given ID.
         *
         * @param ID the time zone identifier.
         * @return The time zone for the identifier or GMT, if no such time
         * zone exists.
         */
	static TimeZone* getTimeZone(jakelib::lang::String* ID);

        /**
         * Gets the available IDs according to the given time zone
         * offset.  
         *
         * @param rawOffset the given time zone GMT offset.
         * @return An array of IDs, where the time zone has the specified GMT
         * offset. For example <code>{"Phoenix", "Denver"}</code>, since both have
         * GMT-07:00, but differ in daylight savings behaviour.
         */
	static jakelib::lang::Strings* getAvailableIDs(int rawOffset);

        /**
         * Gets all available IDs.
         *
         * @return An array of all supported IDs.
         */
	static jakelib::lang::Strings* getAvailableIDs();

        /**
         * Returns the time zone under which the host is running.  This
         * can be changed with setDefault.
         *
         * @return the time zone for this host.
         */
	static TimeZone* getDefault();

	static void setDefault(TimeZone* zone);

        /**
         * Test if the other time zone uses the same rule and only
         * possibly differs in ID. This implementation for this particular
         * class will return true if the raw offsets are identical. Subclasses
         * should override this method if they use daylight savings.
         *
         * @return true if this zone has the same raw offset
         */
        virtual jboolean hasSameRules(TimeZone* other);

        /**
         * Returns a clone of this object. I can't imagine, why this is
         * useful for a time zone.
         */
        jakelib::lang::Object* clone();

        /**
         * @brief Called by \c Object::initJakelib2().
         * Do not use otherwise.
         */
        static void initTimeZoneClass();

      private:

	jakelib::lang::String* id;

	static TimeZone* defaultZone;

	//	static const jakelib::lang::String* GMT_ID;

	//	static const int GMT_ID_LENGTH = 3;

	//	static const jakelib::lang::String* CUSTOM_ID     = "Custom";

	//	static NumberFormat* numberFormat;

	//static const TimeZone* GMT;

	//static SimpleTimeZone* parseCustomTimeZone(jakelib::lang::String* id);

        static Hashtable *timezones;

	JAKELIB_DECLARE_CLASS(TimeZone);
      };

  }
}
#endif

