/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * 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 com.android.calendarcommon2;

import android.content.ContentValues;
import android.database.Cursor;
import android.provider.CalendarContract;
import android.text.TextUtils;
import android.text.format.Time;
import android.util.Log;
import android.util.TimeFormatException;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

/**
 * Basic information about a recurrence, following RFC 2445 Section 4.8.5.
 * Contains the RRULEs, RDATE, EXRULEs, and EXDATE properties.
 */
public class RecurrenceSet {

    private final static String TAG = "RecurrenceSet";

    private final static String RULE_SEPARATOR = "\n";
    private final static String FOLDING_SEPARATOR = "\n ";

    // TODO: make these final?
    public EventRecurrence[] rrules = null;
    public long[] rdates = null;
    public EventRecurrence[] exrules = null;
    public long[] exdates = null;

    /**
     * Creates a new RecurrenceSet from information stored in the
     * events table in the CalendarProvider.
     * @param values The values retrieved from the Events table.
     */
    public RecurrenceSet(ContentValues values)
            throws EventRecurrence.InvalidFormatException {
        String rruleStr = values.getAsString(CalendarContract.Events.RRULE);
        String rdateStr = values.getAsString(CalendarContract.Events.RDATE);
        String exruleStr = values.getAsString(CalendarContract.Events.EXRULE);
        String exdateStr = values.getAsString(CalendarContract.Events.EXDATE);
        init(rruleStr, rdateStr, exruleStr, exdateStr);
    }

    /**
     * Creates a new RecurrenceSet from information stored in a database
     * {@link Cursor} pointing to the events table in the
     * CalendarProvider.  The cursor must contain the RRULE, RDATE, EXRULE,
     * and EXDATE columns.
     *
     * @param cursor The cursor containing the RRULE, RDATE, EXRULE, and EXDATE
     * columns.
     */
    public RecurrenceSet(Cursor cursor)
            throws EventRecurrence.InvalidFormatException {
        int rruleColumn = cursor.getColumnIndex(CalendarContract.Events.RRULE);
        int rdateColumn = cursor.getColumnIndex(CalendarContract.Events.RDATE);
        int exruleColumn = cursor.getColumnIndex(CalendarContract.Events.EXRULE);
        int exdateColumn = cursor.getColumnIndex(CalendarContract.Events.EXDATE);
        String rruleStr = cursor.getString(rruleColumn);
        String rdateStr = cursor.getString(rdateColumn);
        String exruleStr = cursor.getString(exruleColumn);
        String exdateStr = cursor.getString(exdateColumn);
        init(rruleStr, rdateStr, exruleStr, exdateStr);
    }

    public RecurrenceSet(String rruleStr, String rdateStr,
                  String exruleStr, String exdateStr)
            throws EventRecurrence.InvalidFormatException {
        init(rruleStr, rdateStr, exruleStr, exdateStr);
    }

    private void init(String rruleStr, String rdateStr,
                      String exruleStr, String exdateStr)
            throws EventRecurrence.InvalidFormatException {
        if (!TextUtils.isEmpty(rruleStr) || !TextUtils.isEmpty(rdateStr)) {

            if (!TextUtils.isEmpty(rruleStr)) {
                String[] rruleStrs = rruleStr.split(RULE_SEPARATOR);
                rrules = new EventRecurrence[rruleStrs.length];
                for (int i = 0; i < rruleStrs.length; ++i) {
                    EventRecurrence rrule = new EventRecurrence();
                    rrule.parse(rruleStrs[i]);
                    rrules[i] = rrule;
                }
            }

            if (!TextUtils.isEmpty(rdateStr)) {
                rdates = parseRecurrenceDates(rdateStr);
            }

            if (!TextUtils.isEmpty(exruleStr)) {
                String[] exruleStrs = exruleStr.split(RULE_SEPARATOR);
                exrules = new EventRecurrence[exruleStrs.length];
                for (int i = 0; i < exruleStrs.length; ++i) {
                    EventRecurrence exrule = new EventRecurrence();
                    exrule.parse(exruleStr);
                    exrules[i] = exrule;
                }
            }

            if (!TextUtils.isEmpty(exdateStr)) {
                final List<Long> list = new ArrayList<Long>();
                for (String exdate : exdateStr.split(RULE_SEPARATOR)) {
                    final long[] dates = parseRecurrenceDates(exdate);
                    for (long date : dates) {
                        list.add(date);
                    }
                }
                exdates = new long[list.size()];
                for (int i = 0, n = list.size(); i < n; i++) {
                    exdates[i] = list.get(i);
                }
            }
        }
    }

    /**
     * Returns whether or not a recurrence is defined in this RecurrenceSet.
     * @return Whether or not a recurrence is defined in this RecurrenceSet.
     */
    public boolean hasRecurrence() {
        return (rrules != null || rdates != null);
    }

    /**
     * Parses the provided RDATE or EXDATE string into an array of longs
     * representing each date/time in the recurrence.
     * @param recurrence The recurrence to be parsed.
     * @return The list of date/times.
     */
    public static long[] parseRecurrenceDates(String recurrence)
            throws EventRecurrence.InvalidFormatException{
        // TODO: use "local" time as the default.  will need to handle times
        // that end in "z" (UTC time) explicitly at that point.
        String tz = Time.TIMEZONE_UTC;
        int tzidx = recurrence.indexOf(";");
        if (tzidx != -1) {
            tz = recurrence.substring(0, tzidx);
            recurrence = recurrence.substring(tzidx + 1);
        }
        Time time = new Time(tz);
        String[] rawDates = recurrence.split(",");
        int n = rawDates.length;
        long[] dates = new long[n];
        for (int i = 0; i<n; ++i) {
            // The timezone is updated to UTC if the time string specified 'Z'.
            try {
                time.parse(rawDates[i]);
            } catch (TimeFormatException e) {
                throw new EventRecurrence.InvalidFormatException(
                        "TimeFormatException thrown when parsing time " + rawDates[i]
                                + " in recurrence " + recurrence);

            }
            dates[i] = time.toMillis(false /* use isDst */);
            time.timezone = tz;
        }
        return dates;
    }

    /**
     * Populates the database map of values with the appropriate RRULE, RDATE,
     * EXRULE, and EXDATE values extracted from the parsed iCalendar component.
     * @param component The iCalendar component containing the desired
     * recurrence specification.
     * @param values The db values that should be updated.
     * @return true if the component contained the necessary information
     * to specify a recurrence.  The required fields are DTSTART,
     * one of DTEND/DURATION, and one of RRULE/RDATE.  Returns false if
     * there was an error, including if the date is out of range.
     */
    public static boolean populateContentValues(ICalendar.Component component,
            ContentValues values) {
        try {
            ICalendar.Property dtstartProperty =
                    component.getFirstProperty("DTSTART");
            String dtstart = dtstartProperty.getValue();
            ICalendar.Parameter tzidParam =
                    dtstartProperty.getFirstParameter("TZID");
            // NOTE: the timezone may be null, if this is a floating time.
            String tzid = tzidParam == null ? null : tzidParam.value;
            Time start = new Time(tzidParam == null ? Time.TIMEZONE_UTC : tzid);
            boolean inUtc = start.parse(dtstart);
            boolean allDay = start.allDay;

            // We force TimeZone to UTC for "all day recurring events" as the server is sending no
            // TimeZone in DTSTART for them
            if (inUtc || allDay) {
                tzid = Time.TIMEZONE_UTC;
            }

            String duration = computeDuration(start, component);
            String rrule = flattenProperties(component, "RRULE");
            String rdate = extractDates(component.getFirstProperty("RDATE"));
            String exrule = flattenProperties(component, "EXRULE");
            String exdate = extractDates(component.getFirstProperty("EXDATE"));

            if ((TextUtils.isEmpty(dtstart))||
                    (TextUtils.isEmpty(duration))||
                    ((TextUtils.isEmpty(rrule))&&
                            (TextUtils.isEmpty(rdate)))) {
                    if (false) {
                        Log.d(TAG, "Recurrence missing DTSTART, DTEND/DURATION, "
                                    + "or RRULE/RDATE: "
                                    + component.toString());
                    }
                    return false;
            }

            if (allDay) {
                start.timezone = Time.TIMEZONE_UTC;
            }
            long millis = start.toMillis(false /* use isDst */);
            values.put(CalendarContract.Events.DTSTART, millis);
            if (millis == -1) {
                if (false) {
                    Log.d(TAG, "DTSTART is out of range: " + component.toString());
                }
                return false;
            }

            values.put(CalendarContract.Events.RRULE, rrule);
            values.put(CalendarContract.Events.RDATE, rdate);
            values.put(CalendarContract.Events.EXRULE, exrule);
            values.put(CalendarContract.Events.EXDATE, exdate);
            values.put(CalendarContract.Events.EVENT_TIMEZONE, tzid);
            values.put(CalendarContract.Events.DURATION, duration);
            values.put(CalendarContract.Events.ALL_DAY, allDay ? 1 : 0);
            return true;
        } catch (TimeFormatException e) {
            // Something is wrong with the format of this event
            Log.i(TAG,"Failed to parse event: " + component.toString());
            return false;
        }
    }

    // This can be removed when the old CalendarSyncAdapter is removed.
    public static boolean populateComponent(Cursor cursor,
                                            ICalendar.Component component) {

        int dtstartColumn = cursor.getColumnIndex(CalendarContract.Events.DTSTART);
        int durationColumn = cursor.getColumnIndex(CalendarContract.Events.DURATION);
        int tzidColumn = cursor.getColumnIndex(CalendarContract.Events.EVENT_TIMEZONE);
        int rruleColumn = cursor.getColumnIndex(CalendarContract.Events.RRULE);
        int rdateColumn = cursor.getColumnIndex(CalendarContract.Events.RDATE);
        int exruleColumn = cursor.getColumnIndex(CalendarContract.Events.EXRULE);
        int exdateColumn = cursor.getColumnIndex(CalendarContract.Events.EXDATE);
        int allDayColumn = cursor.getColumnIndex(CalendarContract.Events.ALL_DAY);


        long dtstart = -1;
        if (!cursor.isNull(dtstartColumn)) {
            dtstart = cursor.getLong(dtstartColumn);
        }
        String duration = cursor.getString(durationColumn);
        String tzid = cursor.getString(tzidColumn);
        String rruleStr = cursor.getString(rruleColumn);
        String rdateStr = cursor.getString(rdateColumn);
        String exruleStr = cursor.getString(exruleColumn);
        String exdateStr = cursor.getString(exdateColumn);
        boolean allDay = cursor.getInt(allDayColumn) == 1;

        if ((dtstart == -1) ||
            (TextUtils.isEmpty(duration))||
            ((TextUtils.isEmpty(rruleStr))&&
                (TextUtils.isEmpty(rdateStr)))) {
                // no recurrence.
                return false;
        }

        ICalendar.Property dtstartProp = new ICalendar.Property("DTSTART");
        Time dtstartTime = null;
        if (!TextUtils.isEmpty(tzid)) {
            if (!allDay) {
                dtstartProp.addParameter(new ICalendar.Parameter("TZID", tzid));
            }
            dtstartTime = new Time(tzid);
        } else {
            // use the "floating" timezone
            dtstartTime = new Time(Time.TIMEZONE_UTC);
        }

        dtstartTime.set(dtstart);
        // make sure the time is printed just as a date, if all day.
        // TODO: android.pim.Time really should take care of this for us.
        if (allDay) {
            dtstartProp.addParameter(new ICalendar.Parameter("VALUE", "DATE"));
            dtstartTime.allDay = true;
            dtstartTime.hour = 0;
            dtstartTime.minute = 0;
            dtstartTime.second = 0;
        }

        dtstartProp.setValue(dtstartTime.format2445());
        component.addProperty(dtstartProp);
        ICalendar.Property durationProp = new ICalendar.Property("DURATION");
        durationProp.setValue(duration);
        component.addProperty(durationProp);

        addPropertiesForRuleStr(component, "RRULE", rruleStr);
        addPropertyForDateStr(component, "RDATE", rdateStr);
        addPropertiesForRuleStr(component, "EXRULE", exruleStr);
        addPropertyForDateStr(component, "EXDATE", exdateStr);
        return true;
    }

public static boolean populateComponent(ContentValues values,
                                            ICalendar.Component component) {
        long dtstart = -1;
        if (values.containsKey(CalendarContract.Events.DTSTART)) {
            dtstart = values.getAsLong(CalendarContract.Events.DTSTART);
        }
        final String duration = values.getAsString(CalendarContract.Events.DURATION);
        final String tzid = values.getAsString(CalendarContract.Events.EVENT_TIMEZONE);
        final String rruleStr = values.getAsString(CalendarContract.Events.RRULE);
        final String rdateStr = values.getAsString(CalendarContract.Events.RDATE);
        final String exruleStr = values.getAsString(CalendarContract.Events.EXRULE);
        final String exdateStr = values.getAsString(CalendarContract.Events.EXDATE);
        final Integer allDayInteger = values.getAsInteger(CalendarContract.Events.ALL_DAY);
        final boolean allDay = (null != allDayInteger) ? (allDayInteger == 1) : false;

        if ((dtstart == -1) ||
            (TextUtils.isEmpty(duration))||
            ((TextUtils.isEmpty(rruleStr))&&
                (TextUtils.isEmpty(rdateStr)))) {
                // no recurrence.
                return false;
        }

        ICalendar.Property dtstartProp = new ICalendar.Property("DTSTART");
        Time dtstartTime = null;
        if (!TextUtils.isEmpty(tzid)) {
            if (!allDay) {
                dtstartProp.addParameter(new ICalendar.Parameter("TZID", tzid));
            }
            dtstartTime = new Time(tzid);
        } else {
            // use the "floating" timezone
            dtstartTime = new Time(Time.TIMEZONE_UTC);
        }

        dtstartTime.set(dtstart);
        // make sure the time is printed just as a date, if all day.
        // TODO: android.pim.Time really should take care of this for us.
        if (allDay) {
            dtstartProp.addParameter(new ICalendar.Parameter("VALUE", "DATE"));
            dtstartTime.allDay = true;
            dtstartTime.hour = 0;
            dtstartTime.minute = 0;
            dtstartTime.second = 0;
        }

        dtstartProp.setValue(dtstartTime.format2445());
        component.addProperty(dtstartProp);
        ICalendar.Property durationProp = new ICalendar.Property("DURATION");
        durationProp.setValue(duration);
        component.addProperty(durationProp);

        addPropertiesForRuleStr(component, "RRULE", rruleStr);
        addPropertyForDateStr(component, "RDATE", rdateStr);
        addPropertiesForRuleStr(component, "EXRULE", exruleStr);
        addPropertyForDateStr(component, "EXDATE", exdateStr);
        return true;
    }

    public static void addPropertiesForRuleStr(ICalendar.Component component,
                                                String propertyName,
                                                String ruleStr) {
        if (TextUtils.isEmpty(ruleStr)) {
            return;
        }
        String[] rrules = getRuleStrings(ruleStr);
        for (String rrule : rrules) {
            ICalendar.Property prop = new ICalendar.Property(propertyName);
            prop.setValue(rrule);
            component.addProperty(prop);
        }
    }

    private static String[] getRuleStrings(String ruleStr) {
        if (null == ruleStr) {
            return new String[0];
        }
        String unfoldedRuleStr = unfold(ruleStr);
        String[] split = unfoldedRuleStr.split(RULE_SEPARATOR);
        int count = split.length;
        for (int n = 0; n < count; n++) {
            split[n] = fold(split[n]);
        }
        return split;
    }


    private static final Pattern IGNORABLE_ICAL_WHITESPACE_RE =
            Pattern.compile("(?:\\r\\n?|\\n)[ \t]");

    private static final Pattern FOLD_RE = Pattern.compile(".{75}");

    /**
    * fold and unfolds ical content lines as per RFC 2445 section 4.1.
    *
    * <h3>4.1 Content Lines</h3>
    *
    * <p>The iCalendar object is organized into individual lines of text, called
    * content lines. Content lines are delimited by a line break, which is a CRLF
    * sequence (US-ASCII decimal 13, followed by US-ASCII decimal 10).
    *
    * <p>Lines of text SHOULD NOT be longer than 75 octets, excluding the line
    * break. Long content lines SHOULD be split into a multiple line
    * representations using a line "folding" technique. That is, a long line can
    * be split between any two characters by inserting a CRLF immediately
    * followed by a single linear white space character (i.e., SPACE, US-ASCII
    * decimal 32 or HTAB, US-ASCII decimal 9). Any sequence of CRLF followed
    * immediately by a single linear white space character is ignored (i.e.,
    * removed) when processing the content type.
    */
    public static String fold(String unfoldedIcalContent) {
        return FOLD_RE.matcher(unfoldedIcalContent).replaceAll("$0\r\n ");
    }

    public static String unfold(String foldedIcalContent) {
        return IGNORABLE_ICAL_WHITESPACE_RE.matcher(
            foldedIcalContent).replaceAll("");
    }

    public static void addPropertyForDateStr(ICalendar.Component component,
                                              String propertyName,
                                              String dateStr) {
        if (TextUtils.isEmpty(dateStr)) {
            return;
        }

        ICalendar.Property prop = new ICalendar.Property(propertyName);
        String tz = null;
        int tzidx = dateStr.indexOf(";");
        if (tzidx != -1) {
            tz = dateStr.substring(0, tzidx);
            dateStr = dateStr.substring(tzidx + 1);
        }
        if (!TextUtils.isEmpty(tz)) {
            prop.addParameter(new ICalendar.Parameter("TZID", tz));
        }
        prop.setValue(dateStr);
        component.addProperty(prop);
    }

    private static String computeDuration(Time start,
                                          ICalendar.Component component) {
        // see if a duration is defined
        ICalendar.Property durationProperty =
                component.getFirstProperty("DURATION");
        if (durationProperty != null) {
            // just return the duration
            return durationProperty.getValue();
        }

        // must compute a duration from the DTEND
        ICalendar.Property dtendProperty =
                component.getFirstProperty("DTEND");
        if (dtendProperty == null) {
            // no DURATION, no DTEND: 0 second duration
            return "+P0S";
        }
        ICalendar.Parameter endTzidParameter =
                dtendProperty.getFirstParameter("TZID");
        String endTzid = (endTzidParameter == null)
                ? start.timezone : endTzidParameter.value;

        Time end = new Time(endTzid);
        end.parse(dtendProperty.getValue());
        long durationMillis = end.toMillis(false /* use isDst */)
                - start.toMillis(false /* use isDst */);
        long durationSeconds = (durationMillis / 1000);
        if (start.allDay && (durationSeconds % 86400) == 0) {
            return "P" + (durationSeconds / 86400) + "D"; // Server wants this instead of P86400S
        } else {
            return "P" + durationSeconds + "S";
        }
    }

    private static String flattenProperties(ICalendar.Component component,
                                            String name) {
        List<ICalendar.Property> properties = component.getProperties(name);
        if (properties == null || properties.isEmpty()) {
            return null;
        }

        if (properties.size() == 1) {
            return properties.get(0).getValue();
        }

        StringBuilder sb = new StringBuilder();

        boolean first = true;
        for (ICalendar.Property property : component.getProperties(name)) {
            if (first) {
                first = false;
            } else {
                // TODO: use commas.  our RECUR parsing should handle that
                // anyway.
                sb.append(RULE_SEPARATOR);
            }
            sb.append(property.getValue());
        }
        return sb.toString();
    }

    private static String extractDates(ICalendar.Property recurrence) {
        if (recurrence == null) {
            return null;
        }
        ICalendar.Parameter tzidParam =
                recurrence.getFirstParameter("TZID");
        if (tzidParam != null) {
            return tzidParam.value + ";" + recurrence.getValue();
        }
        return recurrence.getValue();
    }
}
