// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html#License
/*
 *******************************************************************************
 * Copyright (C) 2007-2016, International Business Machines Corporation and
 * others. All Rights Reserved.
 *******************************************************************************
 */
package com.ibm.icu.impl;

import java.text.FieldPosition;
import java.text.ParsePosition;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.MissingResourceException;

import com.ibm.icu.lang.UCharacter;
import com.ibm.icu.text.BreakIterator;
import com.ibm.icu.text.DateFormat;
import com.ibm.icu.text.DisplayContext;
import com.ibm.icu.text.MessageFormat;
import com.ibm.icu.text.SimpleDateFormat;
import com.ibm.icu.util.Calendar;
import com.ibm.icu.util.TimeZone;
import com.ibm.icu.util.ULocale;
import com.ibm.icu.util.UResourceBundle;

/**
 * @author srl
 */
public class RelativeDateFormat extends DateFormat {

    /**
     * @author srl
     *
     */
    public static class URelativeString {
        URelativeString(int offset, String string) {
            this.offset = offset;
            this.string = string;
        }
        URelativeString(String offset, String string) {
            this.offset = Integer.parseInt(offset);
            this.string = string;
        }
        public int    offset;
        public String string;
    }

    // copy c'tor?

    /**
     * @param timeStyle The time style for the date and time.
     * @param dateStyle The date style for the date and time.
     * @param locale The locale for the date.
     * @param cal The calendar to be used
     */
    public RelativeDateFormat(int timeStyle, int dateStyle, ULocale locale, Calendar cal) {
        calendar = cal;

        fLocale = locale;
        fTimeStyle = timeStyle;
        fDateStyle = dateStyle;

        if (fDateStyle != DateFormat.NONE) {
            int newStyle = fDateStyle & ~DateFormat.RELATIVE;
            DateFormat df = DateFormat.getDateInstance(newStyle, locale);
            if (df instanceof SimpleDateFormat) {
                fDateTimeFormat = (SimpleDateFormat)df;
            } else {
                throw new IllegalArgumentException("Can't create SimpleDateFormat for date style");
            }
            fDatePattern = fDateTimeFormat.toPattern();
            if (fTimeStyle != DateFormat.NONE) {
                newStyle = fTimeStyle & ~DateFormat.RELATIVE;
                df = DateFormat.getTimeInstance(newStyle, locale);
                if (df instanceof SimpleDateFormat) {
                    fTimePattern = ((SimpleDateFormat)df).toPattern();
                }
            }
        } else {
            // does not matter whether timeStyle is UDAT_NONE, we need something for fDateTimeFormat
            int newStyle = fTimeStyle & ~DateFormat.RELATIVE;
            DateFormat df = DateFormat.getTimeInstance(newStyle, locale);
            if (df instanceof SimpleDateFormat) {
                fDateTimeFormat = (SimpleDateFormat)df;
            } else {
                throw new IllegalArgumentException("Can't create SimpleDateFormat for time style");
            }
            fTimePattern = fDateTimeFormat.toPattern();
        }

        initializeCalendar(null, fLocale);
        loadDates();
        initializeCombinedFormat(calendar, fLocale);
    }

    /**
     * serial version (generated)
     */
    private static final long serialVersionUID = 1131984966440549435L;

    /* (non-Javadoc)
     * @see com.ibm.icu.text.DateFormat#format(com.ibm.icu.util.Calendar, java.lang.StringBuffer, java.text.FieldPosition)
     */
    @Override
    public StringBuffer format(Calendar cal, StringBuffer toAppendTo,
            FieldPosition fieldPosition) {

        String relativeDayString = null;
        DisplayContext capitalizationContext = getContext(DisplayContext.Type.CAPITALIZATION);

        if (fDateStyle != DateFormat.NONE) {
            // calculate the difference, in days, between 'cal' and now.
            int dayDiff = dayDifference(cal);

            // look up string
            relativeDayString = getStringForDay(dayDiff);
        }

        if (fDateTimeFormat != null) {
            if (relativeDayString != null && fDatePattern != null &&
                    (fTimePattern == null || fCombinedFormat == null || combinedFormatHasDateAtStart) ) {
                // capitalize relativeDayString according to context for relative, set formatter no context
                if ( relativeDayString.length() > 0 && UCharacter.isLowerCase(relativeDayString.codePointAt(0)) &&
                     (capitalizationContext == DisplayContext.CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE ||
                        (capitalizationContext == DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU && capitalizationOfRelativeUnitsForListOrMenu) ||
                        (capitalizationContext == DisplayContext.CAPITALIZATION_FOR_STANDALONE && capitalizationOfRelativeUnitsForStandAlone) )) {
                    if (capitalizationBrkIter == null) {
                        // should only happen when deserializing, etc.
                        capitalizationBrkIter = BreakIterator.getSentenceInstance(fLocale);
                    }
                    relativeDayString = UCharacter.toTitleCase(fLocale, relativeDayString, capitalizationBrkIter,
                                    UCharacter.TITLECASE_NO_LOWERCASE | UCharacter.TITLECASE_NO_BREAK_ADJUSTMENT);
                }
                fDateTimeFormat.setContext(DisplayContext.CAPITALIZATION_NONE);
            } else {
                // set our context for the formatter
                fDateTimeFormat.setContext(capitalizationContext);
            }
        }

        if (fDateTimeFormat != null && (fDatePattern != null || fTimePattern != null)) {
            // The new way
            if (fDatePattern == null) {
                // must have fTimePattern
                fDateTimeFormat.applyPattern(fTimePattern);
                fDateTimeFormat.format(cal, toAppendTo, fieldPosition);
            } else if (fTimePattern == null) {
                // must have fDatePattern
                if (relativeDayString != null) {
                    toAppendTo.append(relativeDayString);
                } else {
                    fDateTimeFormat.applyPattern(fDatePattern);
                    fDateTimeFormat.format(cal, toAppendTo, fieldPosition);
                }
            } else {
                String datePattern = fDatePattern; // default;
                if (relativeDayString != null) {
                    // Need to quote the relativeDayString to make it a legal date pattern
                    datePattern = "'" + relativeDayString.replace("'", "''") + "'";
                }
                StringBuffer combinedPattern = new StringBuffer("");
                fCombinedFormat.format(new Object[] {fTimePattern, datePattern}, combinedPattern, new FieldPosition(0));
                fDateTimeFormat.applyPattern(combinedPattern.toString());
                fDateTimeFormat.format(cal, toAppendTo, fieldPosition);
            }
        } else if (fDateFormat != null) {
            // A subset of the old way, for serialization compatibility
            // (just do the date part)
            if (relativeDayString != null) {
                toAppendTo.append(relativeDayString);
            } else {
                fDateFormat.format(cal, toAppendTo, fieldPosition);
            }
        }

        return toAppendTo;
    }

    /* (non-Javadoc)
     * @see com.ibm.icu.text.DateFormat#parse(java.lang.String, com.ibm.icu.util.Calendar, java.text.ParsePosition)
     */
    @Override
    public void parse(String text, Calendar cal, ParsePosition pos) {
        throw new UnsupportedOperationException("Relative Date parse is not implemented yet");
    }

    /* (non-Javadoc)
     * @see com.ibm.icu.text.DateFormat#setContext(com.ibm.icu.text.DisplayContext)
     * Here we override the DateFormat implementation in order to
     * lazily initialize relevant items
     */
    @Override
    public void setContext(DisplayContext context) {
        super.setContext(context);
        if (!capitalizationInfoIsSet &&
              (context==DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU || context==DisplayContext.CAPITALIZATION_FOR_STANDALONE)) {
            initCapitalizationContextInfo(fLocale);
            capitalizationInfoIsSet = true;
        }
        if (capitalizationBrkIter == null && (context==DisplayContext.CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE ||
              (context==DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU && capitalizationOfRelativeUnitsForListOrMenu) ||
              (context==DisplayContext.CAPITALIZATION_FOR_STANDALONE && capitalizationOfRelativeUnitsForStandAlone) )) {
            capitalizationBrkIter = BreakIterator.getSentenceInstance(fLocale);
        }
    }

    private DateFormat fDateFormat; // keep for serialization compatibility
    @SuppressWarnings("unused")
    private DateFormat fTimeFormat; // now unused, keep for serialization compatibility
    private MessageFormat fCombinedFormat; //  the {0} {1} format.
    private SimpleDateFormat fDateTimeFormat = null; // the held date/time formatter
    private String fDatePattern = null;
    private String fTimePattern = null;

    int fDateStyle;
    int fTimeStyle;
    ULocale  fLocale;

    private transient List<URelativeString> fDates = null;

    private boolean combinedFormatHasDateAtStart = false;
    private boolean capitalizationInfoIsSet = false;
    private boolean capitalizationOfRelativeUnitsForListOrMenu = false;
    private boolean capitalizationOfRelativeUnitsForStandAlone = false;
    private transient BreakIterator capitalizationBrkIter = null;

    /**
     * Get the string at a specific offset.
     * @param day day offset ( -1, 0, 1, etc.. ). Does not require sorting by offset.
     * @return the string, or NULL if none at that location.
     */
    private String getStringForDay(int day) {
        if(fDates == null) {
            loadDates();
        }
        for(URelativeString dayItem : fDates) {
            if(dayItem.offset == day) {
                return dayItem.string;
            }
        }
        return null;
    }

    // Sink to get "fields/day/relative".
    private final class RelDateFmtDataSink extends UResource.Sink {

        @Override
        public void put(UResource.Key key, UResource.Value value, boolean noFallback) {
            if (value.getType() == ICUResourceBundle.ALIAS) {
                return;
            }

            UResource.Table table = value.getTable();
            for (int i = 0; table.getKeyAndValue(i, key, value); ++i) {

                int keyOffset;
                try {
                    keyOffset = Integer.parseInt(key.toString());
                }
                catch (NumberFormatException nfe) {
                    // Flag the error?
                    return;
                }
                // Check if already set.
                if (getStringForDay(keyOffset) == null) {
                    URelativeString newDayInfo = new URelativeString(keyOffset, value.getString());
                    fDates.add(newDayInfo);
                }
            }
        }
    }

    /**
     * Load the Date string array
     */
    private synchronized void loadDates() {
        ICUResourceBundle rb = (ICUResourceBundle) UResourceBundle.getBundleInstance(ICUData.ICU_BASE_NAME, fLocale);

        // Use sink mechanism to traverse data structure.
        fDates = new ArrayList<URelativeString>();
        RelDateFmtDataSink sink = new RelDateFmtDataSink();
        rb.getAllItemsWithFallback("fields/day/relative", sink);
    }

    /**
     * Set capitalizationOfRelativeUnitsForListOrMenu, capitalizationOfRelativeUnitsForStandAlone
     */
    private void initCapitalizationContextInfo(ULocale locale) {
        ICUResourceBundle rb = (ICUResourceBundle) UResourceBundle.getBundleInstance(ICUData.ICU_BASE_NAME, locale);
        try {
            ICUResourceBundle rdb = rb.getWithFallback("contextTransforms/relative");
            int[] intVector = rdb.getIntVector();
            if (intVector.length >= 2) {
                capitalizationOfRelativeUnitsForListOrMenu = (intVector[0] != 0);
                capitalizationOfRelativeUnitsForStandAlone = (intVector[1] != 0);
            }
        } catch (MissingResourceException e) {
            // use default
        }
    }

    /**
     * @return the number of days in "until-now"
     */
    private static int dayDifference(Calendar until) {
        Calendar nowCal = (Calendar)until.clone();
        Date nowDate = new Date(System.currentTimeMillis());
        nowCal.clear();
        nowCal.setTime(nowDate);
        int dayDiff = until.get(Calendar.JULIAN_DAY) - nowCal.get(Calendar.JULIAN_DAY);
        return dayDiff;
    }

    /**
     * initializes fCalendar from parameters.  Returns fCalendar as a convenience.
     * @param zone  Zone to be adopted, or NULL for TimeZone::createDefault().
     * @param locale Locale of the calendar
     * @param status Error code
     * @return the newly constructed fCalendar
     */
    private Calendar initializeCalendar(TimeZone zone, ULocale locale) {
        if (calendar == null) {
            if(zone == null) {
                calendar = Calendar.getInstance(locale);
            } else {
                calendar = Calendar.getInstance(zone, locale);
            }
        }
        return calendar;
    }

    private MessageFormat initializeCombinedFormat(Calendar cal, ULocale locale) {
        String pattern;
        ICUResourceBundle rb = (ICUResourceBundle) UResourceBundle.getBundleInstance(
            ICUData.ICU_BASE_NAME, locale);
        String resourcePath = "calendar/" + cal.getType() + "/DateTimePatterns";
        ICUResourceBundle patternsRb= rb.findWithFallback(resourcePath);
        if (patternsRb == null && !cal.getType().equals("gregorian")) {
            // Try again with gregorian, if not already attempted.
            patternsRb = rb.findWithFallback("calendar/gregorian/DateTimePatterns");
        }

        if (patternsRb == null || patternsRb.getSize() < 9) {
            // Undefined or too few elements.
            pattern = "{1} {0}";
        } else {
            int glueIndex = 8;
            if (patternsRb.getSize() >= 13) {
              if (fDateStyle >= DateFormat.FULL && fDateStyle <= DateFormat.SHORT) {
                  glueIndex += fDateStyle + 1;
              } else
                  if (fDateStyle >= DateFormat.RELATIVE_FULL &&
                      fDateStyle <= DateFormat.RELATIVE_SHORT) {
                      glueIndex += fDateStyle + 1 - DateFormat.RELATIVE;
                  }
            }
            int elementType = patternsRb.get(glueIndex).getType();
            if (elementType == UResourceBundle.ARRAY) {
                pattern = patternsRb.get(glueIndex).getString(0);
            } else {
                pattern = patternsRb.getString(glueIndex);
            }
        }
        combinedFormatHasDateAtStart = pattern.startsWith("{1}");
        fCombinedFormat = new MessageFormat(pattern, locale);
        return fCombinedFormat;
    }
}
