/*   Copyright 2004 The Apache Software Foundation
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.apache.xmlbeans;

import java.util.GregorianCalendar;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import java.math.BigDecimal;

/**
 * An XML Schema compatible subclass of {@link java.util.GregorianCalendar GregorianCalendar}.
 * XmlCalendar modifies several key details in the behavior of
 * GregorianCalendar to make it more useful when dealing with XML dates.
 * <p>
 * It is easy to convert between XmlCalendar and {@link GDate}, or to
 * parse or emit an XmlCalendar using a standard XML Schema
 * lexical representation.
 * <ol>
 * <li>
 * To match XML Schema dates, this XmlCalendar is a fully proleptic
 * Gregorian calendar by default, which means that Gregorian calendar
 * rules are applied backwards in time as if they had always been in
 * effect, actual historical circumstances concerning the observance
 * of the 1582 decree of Pope Gregory XIII notwithstanding.
 * </li>
 * <li>
 * In order to better support partially-specified dates for XML Schema,
 * this implementation provides a stable get(field) method
 * that does not modify the instance if you are acessing a field right
 * after it was explicitly set: a set followed by a get will always
 * return the same thing and will not fill in any other fields. However,
 * if you get a field that was not explicitly set, then all the fields
 * are still automatically filled and normalized for you, just like a
 * regular GregorianCalendar. If you wish to force the completion and
 * defaulting of all the fields (without hunting to get one that happens
 * to be unset), you can always do so by calling getTime().
 * </li>
 * <li>
 * When a year is unspecified and needs to be filled in automatically
 * (for example when using a .get or .getTime method as discussed above),
 * the year is defaulted to year 0 (also known as 1 BC).  This is different
 * from {@link GregorianCalendar}, which chooses 1970. The reason 0 is preferable
 * is that it is a leap year and so it permits the date --2-29 to be specified
 * stably. A different default year can be chosen via the static method
 * {@link #setDefaultYear(int) XmlCalendar.setDefaultYear()}, or by setting the 
 * system property "user.defaultyear". If you do change this value, you should 
 * pick another leap year such as 2000 and avoid non-leap years such as 1900.
 * </li>
 * <li>
 * When constructing an XmlCalendar from an XML Schema
 * formatted date or time string or GDate object, the timezone
 * for the calendar is taken from the string if it is present, or
 * taken to be {@link java.util.TimeZone#getDefault() TimeZone.getDefault()} if not.
 * <p>
 *     For example, the XML timezone "Z" is translated to "GMT";
 *     the XML timezone "+05:00" is translated to "GMT+05:00".
 * </p>
 * </li>
 * <li>
 * Finally, this implementation provides a String constructor and a
 * toString() method that comply with the XML Schema conventions
 * for formatting a date. If only a subset of fields have been
 * explicitly set, toString() produces a string with the proper subset
 * of information.
 * </li>
 * </ol>
 */ 
public class XmlCalendar extends GregorianCalendar
{
    /**
     * Constructs an XmlCalendar for a standard XML
     * schema formatted date string.
     * 
     * The parser accepts any of the following formats:
     * 
     * YYYY-MM-DDThh:mm:ss          - dateTime
     * YYYY-MM-DD                   - date
     *            hh:mm:ss          - time
     * YYYY                         - gYear
     *    --MM                      - gMonth
     *      ---DD                   - gDay
     * 
     * The parser actually accepts all 16 combinations of subsets of
     * fields (Y, M, D, T) using the same scheme, even for combinations
     * that are not defined as types in the schema spec, such as
     * year, day, and time:
     * 
     * YYYY--DDThh:mm:ss            - [everything but month specified]
     * 
     * In the string, each field must be padded to its full width, for
     * example, January must be --01, not just --1.
     * 
     * In particular, a year must be padded to at least four digits, so
     * "98" is not a valid year, although "1998" and "0098" are both valid
     * years, unambiguously 19 centuries separated from each other.  A year
     * may also be preceded by a minus symbol: 0000 is 1 BC and -0001 is
     * 2 BC.
     *
     * Finally a timezone is always allowed (yet optional) at the end.
     * Timezones must be either "Z" (UTC, which we translate to GMT),
     * or simple offsets from UTC in the range "-14:00" to "+14:00",
     * for example: "14:30:00-05:00" specifies 2:30 PM in the
     * afternoon at UTC-05:00, which is the same as EST.
     * 
     * If a timezone is not specified, the default TimeZone is used.
     */ 
    public XmlCalendar(String xmlSchemaDateString)
    {
        this(new GDate(xmlSchemaDateString)); // use GDate to parse
    }
    
    /**
     * Constructs an XmlCalendar from a GDate.
     * 
     * If the instance is not completed, you can round-trip to an
     * equivalent GDate by writing "new GDate(new XmlCalendar(gdate))".
     * However, if you access any of the unset fields of the calendar, all
     * the fields will be automatically filled in, so partial dates
     * without timezones or other fields will not round-trip after access.
     */ 
    public XmlCalendar(GDateSpecification date)
    {
        this(GDate.timeZoneForGDate(date), date);
    }
    
    private XmlCalendar(TimeZone tz, GDateSpecification date)
    {
        super(tz);
        setGregorianChange(_beginningOfTime); // proleptic
        clear();
        
        if (date.hasYear())
        {
            int y = date.getYear();
            if (y > 0)
            {
                set(Calendar.ERA, GregorianCalendar.AD);
            }
            else
            {
                set(Calendar.ERA, GregorianCalendar.BC);
                y = 1 - y;
            }
            set(Calendar.YEAR, y);
        }
        if (date.hasMonth())
            set(Calendar.MONTH, date.getMonth() - 1); // note!!
        if (date.hasDay())
            set(Calendar.DAY_OF_MONTH, date.getDay());
        if (date.hasTime())
        {
            set(Calendar.HOUR_OF_DAY, date.getHour());
            set(Calendar.MINUTE, date.getMinute());
            set(Calendar.SECOND, date.getSecond());
            if (date.getFraction().scale() > 0)
                set(Calendar.MILLISECOND, date.getMillisecond());
        }
        if (date.hasTimeZone())
        {
            set(Calendar.ZONE_OFFSET, date.getTimeZoneSign() * 1000 * 60 * (date.getTimeZoneHour() * 60 + date.getTimeZoneMinute()));
            set(Calendar.DST_OFFSET, 0); // note!!  if we don't do this, then GregorianCalendar will pick up DST from the time zone
        }
    }
    
    /**
     * Constructs an XmlCalendar from a Date.
     * 
     * The default TimeZone is used for computing the various fields.
     */
    public XmlCalendar(Date date)
    {
        this(TimeZone.getDefault(), new GDate(date));
        complete();
    }
    
    /**
     * Constructs an XmlCalendar with the specified year, month, day,
     * hours, minutes, seconds, and optional fractional seconds, in
     * the default timezone.
     */
    public XmlCalendar(
            int year,
            int month,
            int day,
            int hour,
            int minute,
            int second,
            BigDecimal fraction)
    {
        this(TimeZone.getDefault(), new GDate(year, month, day, hour, minute, second, fraction));
    }
    
    /**
     * Constructs an XmlCalendar with the specified year, month, day,
     * hours, minutes, seconds, and optional fractional seconds, in
     * the specified timezone.
     */
    public XmlCalendar(
            int year,
            int month,
            int day,
            int hour,
            int minute,
            int second,
            BigDecimal fraction,
            int tzSign,
            int tzHour,
            int tzMinute)
    {
        this(new GDate(year, month, day, hour, minute, second, fraction, tzSign, tzHour, tzMinute));
    }
    

    /**
     * Gets the value for a given time field.
     * 
     * Unlike the GregorianCalendar.get(), peek() does not
     * force a complete of all fields.  If you wish to force a completion
     * of all the fields, call getTime() first.
     */
    public int peek(int field)
    {
        if (!isSet(field) || isTimeSet)
            return super.get(field); // forces a complete
        else
            return internalGet(field); // does not force a complete.
    }

    /**
     * Constructs an empty instance with no fields set.
     */ 
    public XmlCalendar()
    {
        setGregorianChange(_beginningOfTime); // proleptic
        clear();
    }
    
    private static int defaultYear = Integer.MIN_VALUE;
    private static final int DEFAULT_DEFAULT_YEAR = 0;

    /**
     * Returns the default year that is used when no year is specified.
     */ 
    public static int getDefaultYear()
    {
        if (defaultYear == Integer.MIN_VALUE)
        {
            try
            {
                String yearstring = System.getProperty("user.defaultyear");
                if (yearstring != null)
                    defaultYear = Integer.parseInt(yearstring);
                else
                    defaultYear = DEFAULT_DEFAULT_YEAR;
            }
            catch (Throwable t)
            {
                defaultYear = DEFAULT_DEFAULT_YEAR;
            }
        }
        return defaultYear;
    }
    
    /**
     * Sets the default year to be used when no year is specified.
     */ 
    public static void setDefaultYear(int year)
    {
        defaultYear = year;
    }
    
    /**
     * Overrides GregorianCalendar.computeTime to apply a different
     * default year.  (It must be a leap year.)
     */
    protected void computeTime()
    {
        boolean unsetYear = !isSet(YEAR);
        boolean unsetEra = !isSet(ERA);
        if (unsetYear)
            set(YEAR, getDefaultYear());
        if (internalGet(YEAR) == 0)
        {
            set(ERA, BC);
            set(YEAR, 1);
        }
        try
        {
            super.computeTime();
        }
        finally
        {
            if (unsetYear)
                clear(YEAR);
            if (unsetEra)
                clear(ERA);
        }
    }

    /**
     * Overrides GregorianCalendar.computeFields to apply a different
     * default year.  (It must be a leap year.)
     */
    protected void computeFields()
    {
        boolean unsetYear = !isSet(YEAR);
        if (unsetYear)
            set(YEAR, getDefaultYear());
        if (internalGet(YEAR) == 0)
        {
            set(ERA, BC);
            set(YEAR, 1);
        }

        super.computeFields();
    }

    private static Date _beginningOfTime = new Date(Long.MIN_VALUE);
    
    /**
     * Prints the XmlCalendar using a standard XML Schema
     * format, as described in XmlCalendar(String s).
     */
    public String toString()
    {
        return (new GDate(this)).toString(); // use GDate to print
    }

}
