/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  The ASF licenses this file to You
 * 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.  For additional information regarding
 * copyright in this work, please see the NOTICE file in the top level
 * directory of this distribution.
 */

package org.apache.roller.util;

import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import org.apache.commons.lang3.StringUtils;


/**
 * General purpose date utilities.
 *
 * TODO: all date handling functions need to be aware of locale and timezone.
 */
public abstract class DateUtil {
    
    public static final long MILLIS_IN_DAY = 86400000;
    
    // a bunch of date formats
    private static final String FORMAT_DEFAULT_DATE = "dd.MM.yyyy";
    private static final String FORMAT_DEFAULT_DATE_MINIMAL = "d.M.yy";
    private static final String FORMAT_DEFAULT_TIMESTAMP = "yyyy-MM-dd HH:mm:ss.SSS";
    
    private static final String FORMAT_FRIENDLY_TIMESTAMP = "dd.MM.yyyy HH:mm:ss";
    
    private static final String FORMAT_6CHARS = "yyyyMM";
    private static final String FORMAT_8CHARS = "yyyyMMdd";
    
    private static final String FORMAT_ISO_8601 = "yyyy-MM-dd'T'HH:mm:ssZ";
    private static final String FORMAT_ISO_8601_DAY = "yyyy-MM-dd";
    
    private static final String FORMAT_RFC_822 = "EEE, d MMM yyyy HH:mm:ss Z";
    
    
    /**
     * Returns a Date set to the first possible millisecond of the day, just
     * after midnight. If a null day is passed in, a new Date is created.
     * midnight (00m 00h 00s)
     */
    public static Date getStartOfDay(Date day) {
        return getStartOfDay(day, Calendar.getInstance());
    }
    
    
    /**
     * Returns a Date set to the first possible millisecond of the day, just
     * after midnight. If a null day is passed in, a new Date is created.
     * midnight (00m 00h 00s)
     */
    public static Date getStartOfDay(Date day, Calendar cal) {
        if (day == null) {
            day = new Date();
        }
        cal.setTime(day);
        cal.set(Calendar.HOUR_OF_DAY, cal.getMinimum(Calendar.HOUR_OF_DAY));
        cal.set(Calendar.MINUTE,      cal.getMinimum(Calendar.MINUTE));
        cal.set(Calendar.SECOND,      cal.getMinimum(Calendar.SECOND));
        cal.set(Calendar.MILLISECOND, cal.getMinimum(Calendar.MILLISECOND));
        return cal.getTime();
    }
    
    
    /**
     * Returns a Date set to the last possible millisecond of the day, just
     * before midnight. If a null day is passed in, a new Date is created.
     * midnight (00m 00h 00s)
     */
    public static Date getEndOfDay(Date day) {
        return getEndOfDay(day,Calendar.getInstance());
    }
    
    
    public static Date getEndOfDay(Date day,Calendar cal) {
        if (day == null) {
            day = new Date();
        }
        cal.setTime(day);
        cal.set(Calendar.HOUR_OF_DAY, cal.getMaximum(Calendar.HOUR_OF_DAY));
        cal.set(Calendar.MINUTE,      cal.getMaximum(Calendar.MINUTE));
        cal.set(Calendar.SECOND,      cal.getMaximum(Calendar.SECOND));
        cal.set(Calendar.MILLISECOND, cal.getMaximum(Calendar.MILLISECOND));
        return cal.getTime();
    }
    
    
    /**
     * Returns a Date set to the first possible millisecond of the hour.
     * If a null day is passed in, a new Date is created.
     */
    public static Date getStartOfHour(Date day) {
        return getStartOfHour(day, Calendar.getInstance());
    }
    
    
    /**
     * Returns a Date set to the first possible millisecond of the hour.
     * If a null day is passed in, a new Date is created.
     */
    public static Date getStartOfHour(Date day, Calendar cal) {
        if (day == null) {
            day = new Date();
        }
        cal.setTime(day);
        cal.set(Calendar.MINUTE,      cal.getMinimum(Calendar.MINUTE));
        cal.set(Calendar.SECOND,      cal.getMinimum(Calendar.SECOND));
        cal.set(Calendar.MILLISECOND, cal.getMinimum(Calendar.MILLISECOND));
        return cal.getTime();
    }
    
    
    /**
     * Returns a Date set to the last possible millisecond of the day, just
     * before midnight. If a null day is passed in, a new Date is created.
     * midnight (00m 00h 00s)
     */
    public static Date getEndOfHour(Date day) {
        return getEndOfHour(day, Calendar.getInstance());
    }
    
    
    public static Date getEndOfHour(Date day, Calendar cal) {
        if (day == null || cal == null) {
            return day;
        }
        
        cal.setTime(day);
        cal.set(Calendar.MINUTE,      cal.getMaximum(Calendar.MINUTE));
        cal.set(Calendar.SECOND,      cal.getMaximum(Calendar.SECOND));
        cal.set(Calendar.MILLISECOND, cal.getMaximum(Calendar.MILLISECOND));
        return cal.getTime();
    }
    
    
    /**
     * Returns a Date set to the first possible millisecond of the minute.
     * If a null day is passed in, a new Date is created.
     */
    public static Date getStartOfMinute(Date day) {
        return getStartOfMinute(day, Calendar.getInstance());
    }
    
    
    /**
     * Returns a Date set to the first possible millisecond of the minute.
     * If a null day is passed in, a new Date is created.
     */
    public static Date getStartOfMinute(Date day, Calendar cal) {
        if (day == null) {
            day = new Date();
        }
        cal.setTime(day);
        cal.set(Calendar.SECOND,      cal.getMinimum(Calendar.SECOND));
        cal.set(Calendar.MILLISECOND, cal.getMinimum(Calendar.MILLISECOND));
        return cal.getTime();
    }
    
    
    /**
     * Returns a Date set to the last possible millisecond of the minute.
     * If a null day is passed in, a new Date is created.
     */
    public static Date getEndOfMinute(Date day) {
        return getEndOfMinute(day, Calendar.getInstance());
    }
    
    
    public static Date getEndOfMinute(Date day, Calendar cal) {
        if (day == null || cal == null) {
            return day;
        }
        
        cal.setTime(day);
        cal.set(Calendar.SECOND,      cal.getMaximum(Calendar.SECOND));
        cal.set(Calendar.MILLISECOND, cal.getMaximum(Calendar.MILLISECOND));
        return cal.getTime();
    }
    
    
    /**
     * Returns a Date set to the first possible millisecond of the month, just
     * after midnight. If a null day is passed in, a new Date is created.
     * midnight (00m 00h 00s)
     */
    public static Date getStartOfMonth(Date day) {
        return getStartOfMonth(day, Calendar.getInstance());
    }
    
    
    public static Date getStartOfMonth(Date day, Calendar cal) {
        if (day == null) {
            day = new Date();
        }
        cal.setTime(day);
        
        // set time to start of day
        cal.set(Calendar.HOUR_OF_DAY, cal.getMinimum(Calendar.HOUR_OF_DAY));
        cal.set(Calendar.MINUTE,      cal.getMinimum(Calendar.MINUTE));
        cal.set(Calendar.SECOND,      cal.getMinimum(Calendar.SECOND));
        cal.set(Calendar.MILLISECOND, cal.getMinimum(Calendar.MILLISECOND));
        
        // set time to first day of month
        cal.set(Calendar.DAY_OF_MONTH, 1);
        
        return cal.getTime();
    }
    
    
    /**
     * Returns a Date set to the last possible millisecond of the month, just
     * before midnight. If a null day is passed in, a new Date is created.
     * midnight (00m 00h 00s)
     */
    public static Date getEndOfMonth(Date day) {
        return getEndOfMonth(day, Calendar.getInstance());
    }
    
    
    public static Date getEndOfMonth(Date day,Calendar cal) {
        if (day == null) {
            day = new Date();
        }
        cal.setTime(day);
        
        // set time to end of day
        cal.set(Calendar.HOUR_OF_DAY, cal.getMaximum(Calendar.HOUR_OF_DAY));
        cal.set(Calendar.MINUTE,      cal.getMaximum(Calendar.MINUTE));
        cal.set(Calendar.SECOND,      cal.getMaximum(Calendar.SECOND));
        cal.set(Calendar.MILLISECOND, cal.getMaximum(Calendar.MILLISECOND));
        
        // set time to first day of month
        cal.set(Calendar.DAY_OF_MONTH, 1);
        
        // add one month
        cal.add(Calendar.MONTH, 1);
        
        // back up one day
        cal.add(Calendar.DAY_OF_MONTH, -1);
        
        return cal.getTime();
    }
    
    
    /**
     * Returns a Date set just to Noon, to the closest possible millisecond
     * of the day. If a null day is passed in, a new Date is created.
     * noon (00m 12h 00s)
     */
    public static Date getNoonOfDay(Date day, Calendar cal) {
        if (day == null) {
            day = new Date();
        }
        cal.setTime(day);
        cal.set(Calendar.HOUR_OF_DAY, 12);
        cal.set(Calendar.MINUTE,      cal.getMinimum(Calendar.MINUTE));
        cal.set(Calendar.SECOND,      cal.getMinimum(Calendar.SECOND));
        cal.set(Calendar.MILLISECOND, cal.getMinimum(Calendar.MILLISECOND));
        return cal.getTime();
    }
    
    
    /**
     * Returns a java.sql.Timestamp equal to the current time
     **/
    public static java.sql.Timestamp now() {
        return new java.sql.Timestamp(new java.util.Date().getTime());
    }
    
    
    /**
     * Returns a string the represents the passed-in date parsed
     * according to the passed-in format.  Returns an empty string
     * if the date or the format is null.
     **/
    public static String format(Date aDate, SimpleDateFormat aFormat) {
        if (aDate == null || aFormat == null ) { return ""; }
        synchronized (aFormat) {
            return aFormat.format(aDate);
        }
    }
    
    
    /**
     * Returns a Date using the passed-in string and format.  Returns null if the string
     * is null or empty or if the format is null.  The string must match the format.
     **/
    public static Date parse(String aValue, SimpleDateFormat aFormat) throws ParseException {
        if (StringUtils.isEmpty(aValue) || aFormat == null) {
            return null;
        }
        synchronized(aFormat) {
            return aFormat.parse(aValue);
        }
    }
    
    
    /**
     * Returns true if endDate is after startDate or if startDate equals endDate
     * or if they are the same date.  Returns false if either value is null.
     **/
    public static boolean isValidDateRange(Date startDate, Date endDate) {
        return isValidDateRange(startDate, endDate, true);
    }
    
    
    /**
     * Returns true if endDate is after startDate or if startDate equals endDate.
     * Returns false if either value is null.  If equalOK, returns true if the
     * dates are equal.
     **/
    public static boolean isValidDateRange(Date startDate, Date endDate, boolean equalOK) {
        // false if either value is null
        if (startDate == null || endDate == null) { return false; }
        
        if (equalOK && startDate.equals(endDate)) {
            // true if they are equal
            return true;
        }
        
        // true if endDate after startDate
        if (endDate.after(startDate)) {
            return true;
        }
        
        return false;
    }
    
    
    // convenience method returns minimal date format
    public static SimpleDateFormat defaultDateFormat() {
        return DateUtil.friendlyDateFormat(true);
    }
    
    
    // convenience method returns minimal date format
    public static java.text.SimpleDateFormat minimalDateFormat() {
        return friendlyDateFormat(true);
    }
    
    
    // convenience method that returns friendly data format
    // using full month, day, year digits.
    public static SimpleDateFormat fullDateFormat() {
        return friendlyDateFormat(false);
    }
    
    
    /** 
     * Returns a "friendly" date format.
     * @param minimalFormat Should the date format allow single digits.
     **/
    public static SimpleDateFormat friendlyDateFormat(boolean minimalFormat) {
        if (minimalFormat) {
            return new SimpleDateFormat(FORMAT_DEFAULT_DATE_MINIMAL);
        }
        
        return new SimpleDateFormat(FORMAT_DEFAULT_DATE);
    }
    
    
    // returns full timestamp format
    public static SimpleDateFormat defaultTimestampFormat() {
        return new SimpleDateFormat(FORMAT_DEFAULT_TIMESTAMP);
    }
    
    
    // convenience method returns long friendly timestamp format
    public static SimpleDateFormat friendlyTimestampFormat() {
        return new SimpleDateFormat(FORMAT_FRIENDLY_TIMESTAMP);
    }
    
    
    // convenience method returns minimal date format
    public static SimpleDateFormat get8charDateFormat() {
        return new SimpleDateFormat(FORMAT_8CHARS);
    }
    
    
    // convenience method returns minimal date format
    public static SimpleDateFormat get6charDateFormat() {
        return new SimpleDateFormat(FORMAT_6CHARS);
    }
    
    
    // convenience method returns minimal date format
    public static SimpleDateFormat getIso8601DateFormat() {
        return new SimpleDateFormat(FORMAT_ISO_8601);
    }
    
    
    // convenience method returns minimal date format
    public static SimpleDateFormat getIso8601DayDateFormat() {
        return new SimpleDateFormat(FORMAT_ISO_8601_DAY);
    }
    
    
    // convenience method returns minimal date format
    public static SimpleDateFormat getRfc822DateFormat() {
        // http://www.w3.org/Protocols/rfc822/Overview.html#z28
        // Using Locale.US to fix ROL-725 and ROL-628
        return new SimpleDateFormat(FORMAT_RFC_822, Locale.US);
    }
    
    
    // convenience method
    public static String defaultDate(Date date) {
        return format(date, defaultDateFormat());
    }
    
    
    // convenience method using minimal date format
    public static String minimalDate(Date date) {
        return format(date, DateUtil.minimalDateFormat());
    }
    
    
    public static String fullDate(Date date) {
        return format(date, DateUtil.fullDateFormat());
    }
    
    
    /**
     * Format the date using the "friendly" date format.
     */
    public static String friendlyDate(Date date, boolean minimalFormat) {
        return format(date, friendlyDateFormat(minimalFormat));
    }
    
    
    // convenience method
    public static String friendlyDate(Date date) {
        return format(date, friendlyDateFormat(true));
    }
    
    
    // convenience method
    public static String defaultTimestamp(Date date) {
        return format(date, defaultTimestampFormat());
    }
    
    
    // convenience method returns long friendly formatted timestamp
    public static String friendlyTimestamp(Date date) {
        return format(date, friendlyTimestampFormat());
    }
    
    
    // convenience method returns 8 char day stamp YYYYMMDD
    public static String format8chars(Date date) {
        return format(date, get8charDateFormat());
    }

    // convenience method returns 8 char day stamp YYYYMMDD using time zone
    public static String format8chars(Date date, TimeZone tz) {
        SimpleDateFormat formatter = get8charDateFormat();
        formatter.setTimeZone(tz);
        return format(date, formatter);
    }

    // convenience method returns 6 char month stamp YYYYMM
    public static String format6chars(Date date) {
        return format(date, get6charDateFormat());
    }

    // convenience method returns 6 char month stamp YYYYMM using time zone
    public static String format6chars(Date date, TimeZone tz) {
        SimpleDateFormat formatter = get6charDateFormat();
        formatter.setTimeZone(tz);
        return format(date, formatter);
    }

    // convenience method returns long friendly formatted timestamp
    public static String formatIso8601Day(Date date) {
        return format(date, getIso8601DayDateFormat());
    }
    
    
    public static String formatRfc822(Date date) {
        return format(date, getRfc822DateFormat());
    }
    
    
    // This is a hack, but it seems to work
    public static String formatIso8601(Date date) {
        if (date == null) {
            return "";
        }
        
        // Add a colon 2 chars before the end of the string
        // to make it a valid ISO-8601 date.
        
        String str = format(date, getIso8601DateFormat());
        StringBuilder sb = new StringBuilder();
        sb.append( str.substring(0,str.length()-2) );
        sb.append( ":" );
        sb.append( str.substring(str.length()-2) );
        return sb.toString();
    }
    
    
    public static Date parseIso8601(String value) throws Exception {
        return ISO8601DateParser.parse(value);
    }
    
    
    /**
     * Parse data as either 6-char or 8-char format.
     */
    public static Date parseWeblogURLDateString(String dateString, TimeZone tz, Locale locale) {
        
        Date ret = new Date();
        SimpleDateFormat char8DateFormat = DateUtil.get8charDateFormat();
        SimpleDateFormat char6DateFormat = DateUtil.get6charDateFormat();
        
        if (dateString != null
                && dateString.length()==8
                && StringUtils.isNumeric(dateString) ) {
            ParsePosition pos = new ParsePosition(0);
            ret = char8DateFormat.parse(dateString, pos);
            
            // make sure the requested date is not in the future
            Date today = null;
            Calendar todayCal = Calendar.getInstance();
            todayCal = Calendar.getInstance(tz, locale);
            todayCal.setTime(new Date());
            today = todayCal.getTime();
            if(ret.after(today)) {
                ret = today;
            }
            
        } else if(dateString != null
                && dateString.length()==6
                && StringUtils.isNumeric(dateString)) {
            ParsePosition pos = new ParsePosition(0);
            ret = char6DateFormat.parse(dateString, pos);
            
            // make sure the requested date is not in the future
            Calendar todayCal = Calendar.getInstance();
            todayCal = Calendar.getInstance(tz, locale);
            todayCal.setTime(new Date());
            Date today = todayCal.getTime();
            if(ret.after(today)) {
                ret = today;
            }
        }
        
        return ret;
    }
    
}
