/*
 * 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 org.apache.cassandra.cql3;

import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.google.common.base.Objects;

import org.apache.cassandra.serializers.MarshalException;

import static org.apache.cassandra.cql3.statements.RequestValidations.checkTrue;
import static org.apache.cassandra.cql3.statements.RequestValidations.invalidRequest;
import static org.apache.commons.lang3.time.DateUtils.MILLIS_PER_DAY;

/**
 * Represents a duration. A durations store separately months, days, and seconds due to the fact that
 * the number of days in a month varies, and a day can have 23 or 25 hours if a daylight saving is involved.
 */
public final class Duration
{
    public static final long NANOS_PER_MICRO = 1000L;
    public static final long NANOS_PER_MILLI = 1000 * NANOS_PER_MICRO;
    public static final long NANOS_PER_SECOND = 1000 * NANOS_PER_MILLI;
    public static final long NANOS_PER_MINUTE = 60 * NANOS_PER_SECOND;
    public static final long NANOS_PER_HOUR = 60 * NANOS_PER_MINUTE;
    public static final int DAYS_PER_WEEK = 7;
    public static final int MONTHS_PER_YEAR = 12;

    /**
     * The Regexp used to parse the duration provided as String.
     */
    private static final Pattern STANDARD_PATTERN =
            Pattern.compile("\\G(\\d+)(y|Y|mo|MO|mO|Mo|w|W|d|D|h|H|s|S|ms|MS|mS|Ms|us|US|uS|Us|µs|µS|ns|NS|nS|Ns|m|M)");

    /**
     * The Regexp used to parse the duration when provided in the ISO 8601 format with designators.
     */
    private static final Pattern ISO8601_PATTERN =
            Pattern.compile("P((\\d+)Y)?((\\d+)M)?((\\d+)D)?(T((\\d+)H)?((\\d+)M)?((\\d+)S)?)?");

    /**
     * The Regexp used to parse the duration when provided in the ISO 8601 format with designators.
     */
    private static final Pattern ISO8601_WEEK_PATTERN = Pattern.compile("P(\\d+)W");

    /**
     * The Regexp used to parse the duration when provided in the ISO 8601 alternative format.
     */
    private static final Pattern ISO8601_ALTERNATIVE_PATTERN =
            Pattern.compile("P(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})");

    /**
     * The number of months.
     */
    private final int months;

    /**
     * The number of days.
     */
    private final int days;

    /**
     * The number of nanoseconds.
     */
    private final long nanoseconds;

    /**
     * Creates a duration. A duration can be negative.
     * In this case all the non zero values must be negatives.
     *
     * @param months the number of months
     * @param days the number of days
     * @param nanoseconds the number of nanoseconds
     */
    private Duration(int months, int days, long nanoseconds)
    {
        // Makes sure that all the values are negatives if one of them is
        assert (months >= 0 && days >= 0 && nanoseconds >= 0)
            || ((months <= 0 && days <=0 && nanoseconds <=0));

        this.months = months;
        this.days = days;
        this.nanoseconds = nanoseconds;
    }

    public static Duration newInstance(int months, int days, long nanoseconds)
    {
        return new Duration(months, days, nanoseconds);
    }

    /**
     * Converts a <code>String</code> into a duration.
     * <p>The accepted formats are:
     * <ul>
     * <li>multiple digits followed by a time unit like: 12h30m where the time unit can be:
     *   <ul>
     *      <li>{@code y}: years</li>
     *      <li>{@code m}: months</li>
     *      <li>{@code w}: weeks</li>
     *      <li>{@code d}: days</li>
     *      <li>{@code h}: hours</li>
     *      <li>{@code m}: minutes</li>
     *      <li>{@code s}: seconds</li>
     *      <li>{@code ms}: milliseconds</li>
     *      <li>{@code us} or {@code µs}: microseconds</li>
     *      <li>{@code ns}: nanoseconds</li>
     *   </ul>
     * </li>
     * <li>ISO 8601 format:  P[n]Y[n]M[n]DT[n]H[n]M[n]S or P[n]W</li>
     * <li>ISO 8601 alternative format: P[YYYY]-[MM]-[DD]T[hh]:[mm]:[ss]</li>
     * </ul>
     *
     * @param input the <code>String</code> to convert
     * @return a number of nanoseconds
     */
    public static Duration from(String input)
    {
        boolean isNegative = input.startsWith("-");
        String source = isNegative ? input.substring(1) : input;

        if (source.startsWith("P"))
        {
            if (source.endsWith("W"))
                return parseIso8601WeekFormat(isNegative, source);

            if (source.contains("-"))
                return parseIso8601AlternativeFormat(isNegative, source);

            return parseIso8601Format(isNegative, source);
        }
        return parseStandardFormat(isNegative, source);
    }

    private static Duration parseIso8601Format(boolean isNegative, String source)
    {
        Matcher matcher = ISO8601_PATTERN.matcher(source);
        if (!matcher.matches())
            throw invalidRequest("Unable to convert '%s' to a duration", source);

        Builder builder = new Builder(isNegative);
        if (matcher.group(1) != null)
            builder.addYears(groupAsLong(matcher, 2));

        if (matcher.group(3) != null)
            builder.addMonths(groupAsLong(matcher, 4));

        if (matcher.group(5) != null)
            builder.addDays(groupAsLong(matcher, 6));

        // Checks if the String contains time information
        if (matcher.group(7) != null)
        {
            if (matcher.group(8) != null)
                builder.addHours(groupAsLong(matcher, 9));

            if (matcher.group(10) != null)
                builder.addMinutes(groupAsLong(matcher, 11));

            if (matcher.group(12) != null)
                builder.addSeconds(groupAsLong(matcher, 13));
        }
        return builder.build();
    }

    private static Duration parseIso8601AlternativeFormat(boolean isNegative, String source)
    {
        Matcher matcher = ISO8601_ALTERNATIVE_PATTERN.matcher(source);
        if (!matcher.matches())
            throw invalidRequest("Unable to convert '%s' to a duration", source);

        return new Builder(isNegative).addYears(groupAsLong(matcher, 1))
                                      .addMonths(groupAsLong(matcher, 2))
                                      .addDays(groupAsLong(matcher, 3))
                                      .addHours(groupAsLong(matcher, 4))
                                      .addMinutes(groupAsLong(matcher, 5))
                                      .addSeconds(groupAsLong(matcher, 6))
                                      .build();
    }

    private static Duration parseIso8601WeekFormat(boolean isNegative, String source)
    {
        Matcher matcher = ISO8601_WEEK_PATTERN.matcher(source);
        if (!matcher.matches())
            throw invalidRequest("Unable to convert '%s' to a duration", source);

        return new Builder(isNegative).addWeeks(groupAsLong(matcher, 1))
                                      .build();
    }

    private static Duration parseStandardFormat(boolean isNegative, String source)
    {
        Matcher matcher = STANDARD_PATTERN.matcher(source);
        if (!matcher.find())
            throw invalidRequest("Unable to convert '%s' to a duration", source);

        Builder builder = new Builder(isNegative);
        boolean done = false;

        do
        {
            long number = groupAsLong(matcher, 1);
            String symbol = matcher.group(2);
            add(builder, number, symbol);
            done = matcher.end() == source.length();
        }
        while (matcher.find());

        if (!done)
            throw invalidRequest("Unable to convert '%s' to a duration", source);

        return builder.build();
    }

    private static long groupAsLong(Matcher matcher, int group)
    {
        return Long.parseLong(matcher.group(group));
    }

    private static Builder add(Builder builder, long number, String symbol)
    {
        switch (symbol.toLowerCase())
        {
            case "y": return builder.addYears(number);
            case "mo": return builder.addMonths(number);
            case "w": return builder.addWeeks(number);
            case "d": return builder.addDays(number);
            case "h": return builder.addHours(number);
            case "m": return builder.addMinutes(number);
            case "s": return builder.addSeconds(number);
            case "ms": return builder.addMillis(number);
            case "us":
            case "µs": return builder.addMicros(number);
            case "ns": return builder.addNanos(number);
        }
        throw new MarshalException(String.format("Unknown duration symbol '%s'", symbol));
    }

    public int getMonths()
    {
        return months;
    }

    public int getDays()
    {
        return days;
    }

    public long getNanoseconds()
    {
        return nanoseconds;
    }

    /**
     * Adds this duration to the specified time in milliseconds.
     * @param timeInMillis the time to which the duration must be added
     * @return the specified time plus this duration
     */
    public long addTo(long timeInMillis)
    {
        return add(timeInMillis, months, days, nanoseconds);
    }

    /**
     * Substracts this duration from the specified time in milliseconds.
     * @param timeInMillis the time from which the duration must be substracted
     * @return the specified time minus this duration
     */
    public long substractFrom(long timeInMillis)
    {
        return add(timeInMillis, -months, -days, -nanoseconds);
    }

    /**
     * Adds the specified months, days and nanoseconds to the specified time in milliseconds.
     *
     * @param timeInMillis the time to which the months, days and nanoseconds must be added
     * @param months the number of months to add
     * @param days the number of days to add
     * @param nanoseconds the number of nanoseconds to add
     * @return the specified time plus the months, days and nanoseconds
     */
    private static long add(long timeInMillis, int months, int days, long nanoseconds)
    {
        // If the duration does not contains any months we can can ignore daylight saving,
        // as time zones are not supported, and simply look at the milliseconds
        if (months == 0)
        {
            long durationInMillis = (days * MILLIS_PER_DAY) + (nanoseconds / NANOS_PER_MILLI);
            return timeInMillis + durationInMillis;
        }

        Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"), Locale.US);
        calendar.setTimeInMillis(timeInMillis);
        calendar.add(Calendar.MONTH, months);
        calendar.add(Calendar.DAY_OF_MONTH, days);
        calendar.add(Calendar.MILLISECOND, (int) (nanoseconds / NANOS_PER_MILLI));
        return calendar.getTimeInMillis();
    }

    @Override
    public int hashCode()
    {
        return Objects.hashCode(days, months, nanoseconds);
    }

    @Override
    public boolean equals(Object obj)
    {
        if (!(obj instanceof Duration))
            return false;

        Duration other = (Duration) obj;
        return days == other.days
                && months == other.months
                && nanoseconds == other.nanoseconds;
    }

    @Override
    public String toString()
    {
        StringBuilder builder = new StringBuilder();

        if (months < 0 || days < 0 || nanoseconds < 0)
            builder.append('-');

        long remainder = append(builder, Math.abs(months), MONTHS_PER_YEAR, "y");
        append(builder, remainder, 1, "mo");

        append(builder, Math.abs(days), 1, "d");

        if (nanoseconds != 0)
        {
            remainder = append(builder, Math.abs(nanoseconds), NANOS_PER_HOUR, "h");
            remainder = append(builder, remainder, NANOS_PER_MINUTE, "m");
            remainder = append(builder, remainder, NANOS_PER_SECOND, "s");
            remainder = append(builder, remainder, NANOS_PER_MILLI, "ms");
            remainder = append(builder, remainder, NANOS_PER_MICRO, "us");
            append(builder, remainder, 1, "ns");
        }
        return builder.toString();
    }

    /**
     * Checks if that duration has a day precision (nothing bellow the day level).
     * @return {@code true} if that duration has a day precision, {@code false} otherwise
     */
    public boolean hasDayPrecision()
    {
        return getNanoseconds() == 0;
    }

    /**
     * Checks if that duration has a millisecond precision (nothing bellow the millisecond level).
     * @return {@code true} if that duration has a millisecond precision, {@code false} otherwise
     */
    public boolean hasMillisecondPrecision()
    {
        return getNanoseconds() % NANOS_PER_MILLI == 0;
    }

    /**
     * Appends the result of the division to the specified builder if the dividend is not zero.
     *
     * @param builder the builder to append to
     * @param dividend the dividend
     * @param divisor the divisor
     * @param unit the time unit to append after the result of the division
     * @return the remainder of the division
     */
    private static long append(StringBuilder builder, long dividend, long divisor, String unit)
    {
        if (dividend == 0 || dividend < divisor)
            return dividend;

        builder.append(dividend / divisor).append(unit);
        return dividend % divisor;
    }

    private static class Builder
    {
        /**
         * {@code true} if the duration is a negative one, {@code false} otherwise.
         */
        private final boolean isNegative;

        /**
         * The number of months.
         */
        private int months;

        /**
         * The number of days.
         */
        private int days;

        /**
         * The number of nanoseconds.
         */
        private long nanoseconds;

        /**
         * We need to make sure that the values for each units are provided in order.
         */
        private int currentUnitIndex;

        public Builder(boolean isNegative)
        {
            this.isNegative = isNegative;
        }

        /**
         * Adds the specified amount of years.
         *
         * @param numberOfYears the number of years to add.
         * @return this {@code Builder}
         */
        public Builder addYears(long numberOfYears)
        {
            validateOrder(1);
            validateMonths(numberOfYears, MONTHS_PER_YEAR);
            months += numberOfYears * MONTHS_PER_YEAR;
            return this;
        }

        /**
         * Adds the specified amount of months.
         *
         * @param numberOfMonths the number of months to add.
         * @return this {@code Builder}
         */
        public Builder addMonths(long numberOfMonths)
        {
            validateOrder(2);
            validateMonths(numberOfMonths, 1);
            months += numberOfMonths;
            return this;
        }

        /**
         * Adds the specified amount of weeks.
         *
         * @param numberOfWeeks the number of weeks to add.
         * @return this {@code Builder}
         */
        public Builder addWeeks(long numberOfWeeks)
        {
            validateOrder(3);
            validateDays(numberOfWeeks, DAYS_PER_WEEK);
            days += numberOfWeeks * DAYS_PER_WEEK;
            return this;
        }

        /**
         * Adds the specified amount of days.
         *
         * @param numberOfDays the number of days to add.
         * @return this {@code Builder}
         */
        public Builder addDays(long numberOfDays)
        {
            validateOrder(4);
            validateDays(numberOfDays, 1);
            days += numberOfDays;
            return this;
        }

        /**
         * Adds the specified amount of hours.
         *
         * @param numberOfHours the number of hours to add.
         * @return this {@code Builder}
         */
        public Builder addHours(long numberOfHours)
        {
            validateOrder(5);
            validateNanos(numberOfHours, NANOS_PER_HOUR);
            nanoseconds += numberOfHours * NANOS_PER_HOUR;
            return this;
        }

        /**
         * Adds the specified amount of minutes.
         *
         * @param numberOfMinutes the number of minutes to add.
         * @return this {@code Builder}
         */
        public Builder addMinutes(long numberOfMinutes)
        {
            validateOrder(6);
            validateNanos(numberOfMinutes, NANOS_PER_MINUTE);
            nanoseconds += numberOfMinutes * NANOS_PER_MINUTE;
            return this;
        }

        /**
         * Adds the specified amount of seconds.
         *
         * @param numberOfSeconds the number of seconds to add.
         * @return this {@code Builder}
         */
        public Builder addSeconds(long numberOfSeconds)
        {
            validateOrder(7);
            validateNanos(numberOfSeconds, NANOS_PER_SECOND);
            nanoseconds += numberOfSeconds * NANOS_PER_SECOND;
            return this;
        }

        /**
         * Adds the specified amount of milliseconds.
         *
         * @param numberOfMillis the number of milliseconds to add.
         * @return this {@code Builder}
         */
        public Builder addMillis(long numberOfMillis)
        {
            validateOrder(8);
            validateNanos(numberOfMillis, NANOS_PER_MILLI);
            nanoseconds += numberOfMillis * NANOS_PER_MILLI;
            return this;
        }

        /**
         * Adds the specified amount of microseconds.
         *
         * @param numberOfMicros the number of microseconds to add.
         * @return this {@code Builder}
         */
        public Builder addMicros(long numberOfMicros)
        {
            validateOrder(9);
            validateNanos(numberOfMicros, NANOS_PER_MICRO);
            nanoseconds += numberOfMicros * NANOS_PER_MICRO;
            return this;
        }

        /**
         * Adds the specified amount of nanoseconds.
         *
         * @param numberOfNanos the number of nanoseconds to add.
         * @return this {@code Builder}
         */
        public Builder addNanos(long numberOfNanos)
        {
            validateOrder(10);
            validateNanos(numberOfNanos, 1);
            nanoseconds += numberOfNanos;
            return this;
        }

        /**
         * Validates that the total number of months can be stored.
         * @param units the number of units that need to be added
         * @param monthsPerUnit the number of days per unit
         */
        private void validateMonths(long units, int monthsPerUnit)
        {
            validate(units, (Integer.MAX_VALUE - months) / monthsPerUnit, "months");
        }

        /**
         * Validates that the total number of days can be stored.
         * @param units the number of units that need to be added
         * @param daysPerUnit the number of days per unit
         */
        private void validateDays(long units, int daysPerUnit)
        {
            validate(units, (Integer.MAX_VALUE - days) / daysPerUnit, "days");
        }

        /**
         * Validates that the total number of nanoseconds can be stored.
         * @param units the number of units that need to be added
         * @param nanosPerUnit the number of nanoseconds per unit
         */
        private void validateNanos(long units, long nanosPerUnit)
        {
            validate(units, (Long.MAX_VALUE - nanoseconds) / nanosPerUnit, "nanoseconds");
        }

        /**
         * Validates that the specified amount is less than the limit.
         * @param units the number of units to check
         * @param limit the limit on the number of units
         * @param unitName the unit name
         */
        private void validate(long units, long limit, String unitName)
        {
            checkTrue(units <= limit,
                      "Invalid duration. The total number of %s must be less or equal to %s",
                      unitName,
                      Integer.MAX_VALUE);
        }

        /**
         * Validates that the duration values are added in the proper order.
         * @param unitIndex the unit index (e.g. years=1, months=2, ...)
         */
        private void validateOrder(int unitIndex)
        {
            if (unitIndex == currentUnitIndex)
                throw invalidRequest("Invalid duration. The %s are specified multiple times", getUnitName(unitIndex));

            if (unitIndex <= currentUnitIndex)
                throw invalidRequest("Invalid duration. The %s should be after %s",
                      getUnitName(currentUnitIndex),
                      getUnitName(unitIndex));

            currentUnitIndex = unitIndex;
        }

        /**
         * Returns the name of the unit corresponding to the specified index.
         * @param unitIndex the unit index
         * @return the name of the unit corresponding to the specified index.
         */
        private String getUnitName(int unitIndex)
        {
            switch (unitIndex)
            {
                case 1: return "years";
                case 2: return "months";
                case 3: return "weeks";
                case 4: return "days";
                case 5: return "hours";
                case 6: return "minutes";
                case 7: return "seconds";
                case 8: return "milliseconds";
                case 9: return "microseconds";
                case 10: return "nanoseconds";
                default: throw new AssertionError("unknown unit index: " + unitIndex);
            }
        }

        public Duration build()
        {
            return isNegative ? new Duration(-months, -days, -nanoseconds) : new Duration(months, days, nanoseconds);
        }
    }
}
