/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  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.
 */

package freemarker.core;

import java.util.Date;
import java.util.TimeZone;

import freemarker.template.TemplateDateModel;
import freemarker.template.TemplateModelException;
import freemarker.template.utility.DateUtil;
import freemarker.template.utility.DateUtil.CalendarFieldsToDateConverter;
import freemarker.template.utility.DateUtil.DateParseException;
import freemarker.template.utility.DateUtil.DateToISO8601CalendarFactory;
import freemarker.template.utility.StringUtil;

abstract class ISOLikeTemplateDateFormat  extends TemplateDateFormat {
    
    private static final String XS_LESS_THAN_SECONDS_ACCURACY_ERROR_MESSAGE
            = "Less than seconds accuracy isn't allowed by the XML Schema format";
    private final ISOLikeTemplateDateFormatFactory factory;
    private final Environment env;
    protected final int dateType;
    protected final boolean zonelessInput;
    protected final TimeZone timeZone;
    protected final Boolean forceUTC;
    protected final Boolean showZoneOffset;
    protected final int accuracy;

    /**
     * @param formatString The value of the ..._format setting, like "iso nz".
     * @param parsingStart The index of the char in the {@code settingValue} that directly after the prefix that has
     *     indicated the exact formatter class (like "iso" or "xs") 
     */
    public ISOLikeTemplateDateFormat(
            final String formatString, int parsingStart,
            int dateType, boolean zonelessInput,
            TimeZone timeZone,
            ISOLikeTemplateDateFormatFactory factory, Environment env)
            throws InvalidFormatParametersException, UnknownDateTypeFormattingUnsupportedException {
        this.factory = factory;
        this.env = env;
        if (dateType == TemplateDateModel.UNKNOWN) {
            throw new UnknownDateTypeFormattingUnsupportedException();
        }
        
        this.dateType = dateType;
        this.zonelessInput = zonelessInput;
        
        final int ln = formatString.length();
        boolean afterSeparator = false;
        int i = parsingStart;
        int accuracy = DateUtil.ACCURACY_MILLISECONDS;
        Boolean showZoneOffset = null;
        Boolean forceUTC = Boolean.FALSE;
        while (i < ln) {
            final char c = formatString.charAt(i++);
            if (c == '_' || c == ' ') {
                afterSeparator = true;
            } else {
                if (!afterSeparator) {
                    throw new InvalidFormatParametersException(
                            "Missing space or \"_\" before \"" + c + "\" (at char pos. " + i + ").");
                }
                
                switch (c) {
                case 'h':
                case 'm':
                case 's':
                    if (accuracy != DateUtil.ACCURACY_MILLISECONDS) {
                        throw new InvalidFormatParametersException(
                                "Character \"" + c + "\" is unexpected as accuracy was already specified earlier "
                                + "(at char pos. " + i + ").");
                    }
                    switch (c) {
                    case 'h':
                        if (isXSMode()) {
                            throw new InvalidFormatParametersException(
                                    XS_LESS_THAN_SECONDS_ACCURACY_ERROR_MESSAGE);
                        }
                        accuracy = DateUtil.ACCURACY_HOURS;
                        break;
                    case 'm':
                        if (i < ln && formatString.charAt(i) == 's') {
                            i++;
                            accuracy = DateUtil.ACCURACY_MILLISECONDS_FORCED;
                        } else {
                            if (isXSMode()) {
                                throw new InvalidFormatParametersException(
                                        XS_LESS_THAN_SECONDS_ACCURACY_ERROR_MESSAGE);
                            }
                            accuracy = DateUtil.ACCURACY_MINUTES;
                        }
                        break;
                    case 's':
                        accuracy = DateUtil.ACCURACY_SECONDS;
                        break;
                    }
                    break;
                case 'f':
                    if (i < ln && formatString.charAt(i) == 'u') {
                        checkForceUTCNotSet(forceUTC);
                        i++;
                        forceUTC = Boolean.TRUE;
                        break;
                    }
                    // Falls through
                case 'n':
                    if (showZoneOffset != null) {
                        throw new InvalidFormatParametersException(
                                "Character \"" + c + "\" is unexpected as zone offset visibility was already "
                                + "specified earlier. (at char pos. " + i + ").");
                    }
                    switch (c) {
                    case 'n':
                        if (i < ln && formatString.charAt(i) == 'z') {
                            i++;
                            showZoneOffset = Boolean.FALSE;
                        } else {
                            throw new InvalidFormatParametersException(
                                    "\"n\" must be followed by \"z\" (at char pos. " + i + ").");
                        }
                        break;
                    case 'f':
                        if (i < ln && formatString.charAt(i) == 'z') {
                            i++;
                            showZoneOffset = Boolean.TRUE;
                        } else {
                            throw new InvalidFormatParametersException(
                                    "\"f\" must be followed by \"z\" (at char pos. " + i + ").");
                        }
                        break;
                    }
                    break;
                case 'u':
                    checkForceUTCNotSet(forceUTC);
                    forceUTC = null;  // means UTC will be used except for zonelessInput
                    break;
                default:
                    throw new InvalidFormatParametersException(
                            "Unexpected character, " + StringUtil.jQuote(String.valueOf(c))
                            + ". Expected the beginning of one of: h, m, s, ms, nz, fz, u"
                            + " (at char pos. " + i + ").");
                } // switch
                afterSeparator = false;
            } // else
        } // while
        
        this.accuracy = accuracy;
        this.showZoneOffset = showZoneOffset;
        this.forceUTC = forceUTC;
        this.timeZone = timeZone;
    }

    private void checkForceUTCNotSet(Boolean fourceUTC) throws InvalidFormatParametersException {
        if (fourceUTC != Boolean.FALSE) {
            throw new InvalidFormatParametersException(
                    "The UTC usage option was already set earlier.");
        }
    }
    
    @Override
    public final String formatToPlainText(TemplateDateModel dateModel) throws TemplateModelException {
        final Date date = TemplateFormatUtil.getNonNullDate(dateModel);
        return format(
                date,
                dateType != TemplateDateModel.TIME,
                dateType != TemplateDateModel.DATE,
                showZoneOffset == null
                        ? !zonelessInput
                        : showZoneOffset.booleanValue(),
                accuracy,
                (forceUTC == null ? !zonelessInput : forceUTC.booleanValue()) ? DateUtil.UTC : timeZone,
                factory.getISOBuiltInCalendar(env));
    }
    
    protected abstract String format(Date date,
            boolean datePart, boolean timePart, boolean offsetPart,
            int accuracy,
            TimeZone timeZone,
            DateToISO8601CalendarFactory calendarFactory);

    @Override
    @SuppressFBWarnings(value = "RC_REF_COMPARISON_BAD_PRACTICE_BOOLEAN",
            justification = "Known to use the singleton Boolean-s only")
    public final Date parse(String s, int dateType) throws UnparsableValueException {
        CalendarFieldsToDateConverter calToDateConverter = factory.getCalendarFieldsToDateCalculator(env);
        TimeZone tz = forceUTC != Boolean.FALSE ? DateUtil.UTC : timeZone;
        try {
            if (dateType == TemplateDateModel.DATE) {
                return parseDate(s, tz, calToDateConverter);
            } else if (dateType == TemplateDateModel.TIME) {
                return parseTime(s, tz, calToDateConverter);
            } else if (dateType == TemplateDateModel.DATETIME) {
                return parseDateTime(s, tz, calToDateConverter);
            } else {
                throw new BugException("Unexpected date type: " + dateType);
            }
        } catch (DateParseException e) {
            throw new UnparsableValueException(e.getMessage(), e);
        }
    }
    
    protected abstract Date parseDate(
            String s, TimeZone tz,
            CalendarFieldsToDateConverter calToDateConverter) 
            throws DateParseException;
    
    protected abstract Date parseTime(
            String s, TimeZone tz,
            CalendarFieldsToDateConverter calToDateConverter) 
            throws DateParseException;
    
    protected abstract Date parseDateTime(
            String s, TimeZone tz,
            CalendarFieldsToDateConverter calToDateConverter) 
            throws DateParseException;

    @Override
    public final String getDescription() {
        switch (dateType) {
            case TemplateDateModel.DATE: return getDateDescription();
            case TemplateDateModel.TIME: return getTimeDescription();
            case TemplateDateModel.DATETIME: return getDateTimeDescription();
            default: return "<error: wrong format dateType>";
        }
    }
    
    protected abstract String getDateDescription();
    protected abstract String getTimeDescription();
    protected abstract String getDateTimeDescription();
    
    @Override
    public final boolean isLocaleBound() {
        return false;
    }
    
    @Override
    public boolean isTimeZoneBound() {
        return true;
    }

    protected abstract boolean isXSMode();

}
