/*
 * Copyright 2003 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code 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 General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package sun.util.calendar;

import java.util.HashMap;
import java.util.Map;

public class CalendarUtils {

    /**
     * Returns whether the specified year is a leap year in the Gregorian
     * calendar system.
     *
     * @param gregorianYear a Gregorian calendar year
     * @return true if the given year is a leap year in the Gregorian
     * calendar system.
     * @see CalendarDate#isLeapYear
     */
    public static final boolean isGregorianLeapYear(int gregorianYear) {
        return (((gregorianYear % 4) == 0)
                && (((gregorianYear % 100) != 0) || ((gregorianYear % 400) == 0)));
    }

    /**
     * Returns whether the specified year is a leap year in the Julian
     * calendar system. The year number must be a normalized one
     * (e.g., 45 B.C.E. is 1-45).
     *
     * @param normalizedJulianYear a normalized Julian calendar year
     * @return true if the given year is a leap year in the Julian
     * calendar system.
     * @see CalendarDate#isLeapYear
     */
    public static final boolean isJulianLeapYear(int normalizedJulianYear) {
        return (normalizedJulianYear % 4) == 0;
    }

    /**
     * Divides two integers and returns the floor of the quotient.
     * For example, <code>floorDivide(-1, 4)</code> returns -1 while
     * -1/4 is 0.
     *
     * @param n the numerator
     * @param d a divisor that must be greater than 0
     * @return the floor of the quotient
     */
    public static final long floorDivide(long n, long d) {
        return ((n >= 0) ?
                (n / d) : (((n + 1L) / d) - 1L));
    }

    /**
     * Divides two integers and returns the floor of the quotient.
     * For example, <code>floorDivide(-1, 4)</code> returns -1 while
     * -1/4 is 0.
     *
     * @param n the numerator
     * @param d a divisor that must be greater than 0
     * @return the floor of the quotient
     */
    public static final int floorDivide(int n, int d) {
        return ((n >= 0) ?
                (n / d) : (((n + 1) / d) - 1));
    }

    /**
     * Divides two integers and returns the floor of the quotient and
     * the modulus remainder.  For example,
     * <code>floorDivide(-1,4)</code> returns <code>-1</code> with
     * <code>3</code> as its remainder, while <code>-1/4</code> is
     * <code>0</code> and <code>-1%4</code> is <code>-1</code>.
     *
     * @param n the numerator
     * @param d a divisor which must be > 0
     * @param r an array of at least one element in which the value
     * <code>mod(n, d)</code> is returned.
     * @return the floor of the quotient.
     */
    public static final int floorDivide(int n, int d, int[] r) {
        if (n >= 0) {
            r[0] = n % d;
            return n / d;
        }
        int q = ((n + 1) / d) - 1;
        r[0] = n - (q * d);
        return q;
    }

    /**
     * Divides two integers and returns the floor of the quotient and
     * the modulus remainder.  For example,
     * <code>floorDivide(-1,4)</code> returns <code>-1</code> with
     * <code>3</code> as its remainder, while <code>-1/4</code> is
     * <code>0</code> and <code>-1%4</code> is <code>-1</code>.
     *
     * @param n the numerator
     * @param d a divisor which must be > 0
     * @param r an array of at least one element in which the value
     * <code>mod(n, d)</code> is returned.
     * @return the floor of the quotient.
     */
    public static final int floorDivide(long n, int d, int[] r) {
        if (n >= 0) {
            r[0] = (int)(n % d);
            return (int)(n / d);
        }
        int q = (int)(((n + 1) / d) - 1);
        r[0] = (int)(n - (q * d));
        return q;
    }

    public static final long mod(long x, long y) {
        return (x - y * floorDivide(x, y));
    }

    public static final int mod(int x, int y) {
        return (x - y * floorDivide(x, y));
    }

    public static final int amod(int x, int y) {
        int z = mod(x, y);
        return (z == 0) ? y : z;
    }

    public static final long amod(long x, long y) {
        long z = mod(x, y);
        return (z == 0) ? y : z;
    }

    /**
     * Mimics sprintf(buf, "%0*d", decaimal, width).
     */
    public static final StringBuilder sprintf0d(StringBuilder sb, int value, int width) {
        long d = value;
        if (d < 0) {
            sb.append('-');
            d = -d;
            --width;
        }
        int n = 10;
        for (int i = 2; i < width; i++) {
            n *= 10;
        }
        for (int i = 1; i < width && d < n; i++) {
            sb.append('0');
            n /= 10;
        }
        sb.append(d);
        return sb;
    }

    public static final StringBuffer sprintf0d(StringBuffer sb, int value, int width) {
        long d = value;
        if (d < 0) {
            sb.append('-');
            d = -d;
            --width;
        }
        int n = 10;
        for (int i = 2; i < width; i++) {
            n *= 10;
        }
        for (int i = 1; i < width && d < n; i++) {
            sb.append('0');
            n /= 10;
        }
        sb.append(d);
        return sb;
    }
}
