/*
 * Copyright  2003-2005 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.ws.security.util;

import java.text.DateFormat;
import java.text.FieldPosition;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.text.ParseException;
import java.util.Date;
import java.util.TimeZone;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * A {@link DateFormat} for the format of the dateTime simpleType as specified in the
 * XML Schema specification. See <a href="http://www.w3.org/TR/xmlschema-2/#dateTime">
 * XML Schema Part 2: Datatypes, W3C Recommendation 02 May 2001, Section 3.2.7.1</a>.
 *
 * @author Ian P. Springer
 * @author Werner Dittmann
 */
public class XmlSchemaDateFormat extends DateFormat {
    /**
     * Logger.
     */
    private static Log log = LogFactory.getLog(XmlSchemaDateFormat.class);

    /**
     * Message retriever.
     */
    //   private static final MessageRetriever MSG = ResourceKeys.MSG;
    /**
     * DateFormat for Zulu (UTC) form of an XML Schema dateTime string.
     */
    private static final DateFormat DATEFORMAT_XSD_ZULU = new SimpleDateFormat(
            "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");

    static {
        DATEFORMAT_XSD_ZULU.setTimeZone(TimeZone.getTimeZone("UTC"));
    }

    /**
     * This method was snarfed from <tt>org.apache.axis.encoding.ser.CalendarDeserializer</tt>,
     * which was written by Sam Ruby (rubys@us.ibm.com) and Rich Scheuerle (scheu@us.ibm.com).
     * Better error reporting was added.
     *
     * @see DateFormat#parse(java.lang.String)
     */
    public Date parse(String src, ParsePosition parse_pos) {
        Date date;

        // validate fixed portion of format
        int index = 0;
        try {
            if (src != null) {
                if ((src.charAt(0) == '+') || (src.charAt(0) == '-')) {
                    src = src.substring(1);
                }

                if (src.length() < 19) {
                    parse_pos.setIndex(src.length() - 1);
                    handleParseError(parse_pos, "TOO_FEW_CHARS");
                }
                validateChar(src, parse_pos, index = 4, '-', "EXPECTED_DASH");
                validateChar(src, parse_pos, index = 7, '-', "EXPECTED_DASH");
                validateChar(src, parse_pos, index = 10, 'T', "EXPECTED_CAPITAL_T");
                validateChar(src, parse_pos, index = 13, ':', "EXPECTED_COLON_IN_TIME");
                validateChar(src, parse_pos, index = 16, ':', "EXPECTED_COLON_IN_TIME");
            }

            // convert what we have validated so far
            try {
                synchronized (DATEFORMAT_XSD_ZULU) {
                    date = DATEFORMAT_XSD_ZULU.parse((src == null) ? null
                            : (src.substring(0, 19) + ".000Z"));
                }
            } catch (Exception e) {
                throw new NumberFormatException(e.toString());
            }

            index = 19;

            // parse optional milliseconds
            if (src != null) {
                if ((index < src.length()) && (src.charAt(index) == '.')) {
                    int milliseconds = 0;
                    int start = ++index;

                    while ((index < src.length())
                            && Character.isDigit(src.charAt(index))) {
                        index++;
                    }

                    String decimal = src.substring(start, index);

                    if (decimal.length() == 3) {
                        milliseconds = Integer.parseInt(decimal);
                    } else if (decimal.length() < 3) {
                        milliseconds = Integer.parseInt((decimal + "000")
                                .substring(0, 3));
                    } else {
                        milliseconds = Integer
                                .parseInt(decimal.substring(0, 3));

                        if (decimal.charAt(3) >= '5') {
                            ++milliseconds;
                        }
                    }

                    // add milliseconds to the current date
                    date.setTime(date.getTime() + milliseconds);
                }

                // parse optional timezone
                if (((index + 5) < src.length())
                        && ((src.charAt(index) == '+') || (src.charAt(index) == '-'))) {
                    validateCharIsDigit(src, parse_pos, index + 1, "EXPECTED_NUMERAL");
                    validateCharIsDigit(src, parse_pos, index + 2, "EXPECTED_NUMERAL");
                    validateChar(src, parse_pos, index + 3, ':', "EXPECTED_COLON_IN_TIMEZONE");
                    validateCharIsDigit(src, parse_pos, index + 4, "EXPECTED_NUMERAL");
                    validateCharIsDigit(src, parse_pos, index + 5, "EXPECTED_NUMERAL");

                    final int hours = (((src.charAt(index + 1) - '0') * 10) + src
                            .charAt(index + 2)) - '0';
                    final int mins = (((src.charAt(index + 4) - '0') * 10) + src
                            .charAt(index + 5)) - '0';
                    int millisecs = ((hours * 60) + mins) * 60 * 1000;

                    // subtract millisecs from current date to obtain GMT
                    if (src.charAt(index) == '+') {
                        millisecs = -millisecs;
                    }

                    date.setTime(date.getTime() + millisecs);
                    index += 6;
                }

                if ((index < src.length()) && (src.charAt(index) == 'Z')) {
                    index++;
                }

                if (index < src.length()) {
                    handleParseError(parse_pos, "TOO_MANY_CHARS");
                }
            }
        } catch (ParseException pe) {
            log.error(pe.toString(), pe);
            index = 0; // IMPORTANT: this tells DateFormat.parse() to throw a ParseException
            parse_pos.setErrorIndex(index);
            date = null;
        }
        parse_pos.setIndex(index);
        return (date);
    }

    /**
     * @see DateFormat#format(java.util.Date)
     */
    public StringBuffer format(Date date, StringBuffer append_buf,
            FieldPosition field_pos) {
        String str;

        synchronized (DATEFORMAT_XSD_ZULU) {
            str = DATEFORMAT_XSD_ZULU.format(date);
        }

        if (append_buf == null) {
            append_buf = new StringBuffer();
        }

        append_buf.append(str);

        return (append_buf);
    }

    private void validateChar(String str, ParsePosition parse_pos, int index,
            char expected, String error_reason) throws ParseException {
        if (str.charAt(index) != expected) {
            handleParseError(parse_pos, error_reason);
        }
    }

    private void validateCharIsDigit(String str, ParsePosition parse_pos,
            int index, String error_reason) throws ParseException {
        if (!Character.isDigit(str.charAt(index))) {
            handleParseError(parse_pos, error_reason);
        }
    }

    private void handleParseError(ParsePosition parse_pos, String error_reason)
            throws ParseException {
        throw new ParseException("INVALID_XSD_DATETIME", parse_pos.getErrorIndex());
    }

}
