/*
 * Copyright (C) 2018 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 android.app.admin;

import android.app.admin.SystemUpdatePolicy.ValidationFailedException;
import android.util.Log;
import android.util.Pair;

import java.time.LocalDate;
import java.time.MonthDay;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

/**
 * A class that represents one freeze period which repeats <em>annually</em>. A freeze period has
 * two {@link java.time#MonthDay} values that define the start and end dates of the period, both
 * inclusive. If the end date is earlier than the start date, the period is considered wrapped
 * around the year-end. As far as freeze period is concerned, leap year is disregarded and February
 * 29th should be treated as if it were February 28th: so a freeze starting or ending on February
 * 28th is identical to a freeze starting or ending on February 29th. When calulating the length of
 * a freeze or the distance bewteen two freee periods, February 29th is also ignored.
 *
 * @see SystemUpdatePolicy#setFreezePeriods
 */
public class FreezePeriod {
    private static final String TAG = "FreezePeriod";

    private static final int DUMMY_YEAR = 2001;
    static final int DAYS_IN_YEAR = 365; // 365 since DUMMY_YEAR is not a leap year

    private final MonthDay mStart;
    private final MonthDay mEnd;

    /*
     * Start and end dates represented by number of days since the beginning of the year.
     * They are internal representations of mStart and mEnd with normalized Leap year days
     * (Feb 29 == Feb 28 == 59th day of year). All internal calclations are based on
     * these two values so that leap year days are disregarded.
     */
    private final int mStartDay; // [1, 365]
    private final int mEndDay; // [1, 365]

    /**
     * Creates a freeze period by its start and end dates. If the end date is earlier than the start
     * date, the freeze period is considered wrapping year-end.
     */
    public FreezePeriod(MonthDay start, MonthDay end) {
        mStart = start;
        mStartDay = mStart.atYear(DUMMY_YEAR).getDayOfYear();
        mEnd = end;
        mEndDay = mEnd.atYear(DUMMY_YEAR).getDayOfYear();
    }

    /**
     * Returns the start date (inclusive) of this freeze period.
     */
    public MonthDay getStart() {
        return mStart;
    }

    /**
     * Returns the end date (inclusive) of this freeze period.
     */
    public MonthDay getEnd() {
        return mEnd;
    }

    /**
     * @hide
     */
    private FreezePeriod(int startDay, int endDay) {
        mStartDay = startDay;
        mStart = dayOfYearToMonthDay(startDay);
        mEndDay = endDay;
        mEnd = dayOfYearToMonthDay(endDay);
    }

    /** @hide */
    int getLength() {
        return getEffectiveEndDay() - mStartDay + 1;
    }

    /** @hide */
    boolean isWrapped() {
        return mEndDay < mStartDay;
    }

    /**
     * Returns the effective end day, taking wrapping around year-end into consideration
     * @hide
     */
    int getEffectiveEndDay() {
        if (!isWrapped()) {
            return mEndDay;
        } else {
            return mEndDay + DAYS_IN_YEAR;
        }
    }

    /** @hide */
    boolean contains(LocalDate localDate) {
        final int daysOfYear = dayOfYearDisregardLeapYear(localDate);
        if (!isWrapped()) {
            // ---[start---now---end]---
            return (mStartDay <= daysOfYear) && (daysOfYear <= mEndDay);
        } else {
            //    ---end]---[start---now---
            // or ---now---end]---[start---
            return (mStartDay <= daysOfYear) || (daysOfYear <= mEndDay);
        }
    }

    /** @hide */
    boolean after(LocalDate localDate) {
        return mStartDay > dayOfYearDisregardLeapYear(localDate);
    }

    /**
     * Instantiate the current interval to real calendar dates, given a calendar date
     * {@code now}. If the interval contains now, the returned calendar dates should be the
     * current interval (in real calendar dates) that includes now. If the interval does not
     * include now, the returned dates represents the next future interval.
     * The result will always have the same month and dayOfMonth value as the non-instantiated
     * interval itself.
     * @hide
     */
    Pair<LocalDate, LocalDate> toCurrentOrFutureRealDates(LocalDate now) {
        final int nowDays = dayOfYearDisregardLeapYear(now);
        final int startYearAdjustment, endYearAdjustment;
        if (contains(now)) {
            // current interval
            if (mStartDay <= nowDays) {
                //    ----------[start---now---end]---
                // or ---end]---[start---now----------
                startYearAdjustment = 0;
                endYearAdjustment = isWrapped() ? 1 : 0;
            } else /* nowDays <= mEndDay */ {
                // or ---now---end]---[start----------
                startYearAdjustment = -1;
                endYearAdjustment = 0;
            }
        } else {
            // next interval
            if (mStartDay > nowDays) {
                //    ----------now---[start---end]---
                // or ---end]---now---[start----------
                startYearAdjustment = 0;
                endYearAdjustment = isWrapped() ? 1 : 0;
            } else /* mStartDay <= nowDays */ {
                // or ---[start---end]---now----------
                startYearAdjustment = 1;
                endYearAdjustment = 1;
            }
        }
        final LocalDate startDate = LocalDate.ofYearDay(DUMMY_YEAR, mStartDay).withYear(
                now.getYear() + startYearAdjustment);
        final LocalDate endDate = LocalDate.ofYearDay(DUMMY_YEAR, mEndDay).withYear(
                now.getYear() + endYearAdjustment);
        return new Pair<>(startDate, endDate);
    }

    @Override
    public String toString() {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM dd");
        return LocalDate.ofYearDay(DUMMY_YEAR, mStartDay).format(formatter) + " - "
                + LocalDate.ofYearDay(DUMMY_YEAR, mEndDay).format(formatter);
    }

    /** @hide */
    private static MonthDay dayOfYearToMonthDay(int dayOfYear) {
        LocalDate date = LocalDate.ofYearDay(DUMMY_YEAR, dayOfYear);
        return MonthDay.of(date.getMonth(), date.getDayOfMonth());
    }

    /**
     * Treat the supplied date as in a non-leap year and return its day of year.
     * @hide
     */
    private static int dayOfYearDisregardLeapYear(LocalDate date) {
        return date.withYear(DUMMY_YEAR).getDayOfYear();
    }

    /**
     * Compute the number of days between first (inclusive) and second (exclusive),
     * treating all years in between as non-leap.
     * @hide
     */
    public static int distanceWithoutLeapYear(LocalDate first, LocalDate second) {
        return dayOfYearDisregardLeapYear(first) - dayOfYearDisregardLeapYear(second)
                + DAYS_IN_YEAR * (first.getYear() - second.getYear());
    }

    /**
     * Sort, de-duplicate and merge an interval list
     *
     * Instead of using any fancy logic for merging intervals which has loads of corner cases,
     * simply flatten the interval onto a list of 365 calendar days and recreate the interval list
     * from that.
     *
     * This method should return a list of intervals with the following post-conditions:
     *     1. Interval.startDay in strictly ascending order
     *     2. No two intervals should overlap or touch
     *     3. At most one wrapped Interval remains, and it will be at the end of the list
     * @hide
     */
    static List<FreezePeriod> canonicalizePeriods(List<FreezePeriod> intervals) {
        boolean[] taken = new boolean[DAYS_IN_YEAR];
        // First convert the intervals into flat array
        for (FreezePeriod interval : intervals) {
            for (int i = interval.mStartDay; i <= interval.getEffectiveEndDay(); i++) {
                taken[(i - 1) % DAYS_IN_YEAR] = true;
            }
        }
        // Then reconstruct intervals from the array
        List<FreezePeriod> result = new ArrayList<>();
        int i = 0;
        while (i < DAYS_IN_YEAR) {
            if (!taken[i]) {
                i++;
                continue;
            }
            final int intervalStart = i + 1;
            while (i < DAYS_IN_YEAR && taken[i]) i++;
            result.add(new FreezePeriod(intervalStart, i));
        }
        // Check if the last entry can be merged to the first entry to become one single
        // wrapped interval
        final int lastIndex = result.size() - 1;
        if (lastIndex > 0 && result.get(lastIndex).mEndDay == DAYS_IN_YEAR
                && result.get(0).mStartDay == 1) {
            FreezePeriod wrappedInterval = new FreezePeriod(result.get(lastIndex).mStartDay,
                    result.get(0).mEndDay);
            result.set(lastIndex, wrappedInterval);
            result.remove(0);
        }
        return result;
    }

    /**
     * Verifies if the supplied freeze periods satisfies the constraints set out in
     * {@link SystemUpdatePolicy#setFreezePeriods(List)}, and in particular, any single freeze
     * period cannot exceed {@link SystemUpdatePolicy#FREEZE_PERIOD_MAX_LENGTH} days, and two freeze
     * periods need to be at least {@link SystemUpdatePolicy#FREEZE_PERIOD_MIN_SEPARATION} days
     * apart.
     *
     * @hide
     */
    static void validatePeriods(List<FreezePeriod> periods) {
        List<FreezePeriod> allPeriods = FreezePeriod.canonicalizePeriods(periods);
        if (allPeriods.size() != periods.size()) {
            throw SystemUpdatePolicy.ValidationFailedException.duplicateOrOverlapPeriods();
        }
        for (int i = 0; i < allPeriods.size(); i++) {
            FreezePeriod current = allPeriods.get(i);
            if (current.getLength() > SystemUpdatePolicy.FREEZE_PERIOD_MAX_LENGTH) {
                throw SystemUpdatePolicy.ValidationFailedException.freezePeriodTooLong("Freeze "
                        + "period " + current + " is too long: " + current.getLength() + " days");
            }
            FreezePeriod previous = i > 0 ? allPeriods.get(i - 1)
                    : allPeriods.get(allPeriods.size() - 1);
            if (previous != current) {
                final int separation;
                if (i == 0 && !previous.isWrapped()) {
                    // -->[current]---[-previous-]<---
                    separation = current.mStartDay
                            + (DAYS_IN_YEAR - previous.mEndDay) - 1;
                } else {
                    //    --[previous]<--->[current]---------
                    // OR ----prev---]<--->[current]---[prev-
                    separation = current.mStartDay - previous.mEndDay - 1;
                }
                if (separation < SystemUpdatePolicy.FREEZE_PERIOD_MIN_SEPARATION) {
                    throw SystemUpdatePolicy.ValidationFailedException.freezePeriodTooClose("Freeze"
                            + " periods " + previous + " and " + current + " are too close "
                            + "together: " + separation + " days apart");
                }
            }
        }
    }

    /**
     * Verifies that the current freeze periods are still legal, considering the previous freeze
     * periods the device went through. In particular, when combined with the previous freeze
     * period, the maximum freeze length or the minimum freeze separation should not be violated.
     *
     * @hide
     */
    static void validateAgainstPreviousFreezePeriod(List<FreezePeriod> periods,
            LocalDate prevPeriodStart, LocalDate prevPeriodEnd, LocalDate now) {
        if (periods.size() == 0 || prevPeriodStart == null || prevPeriodEnd == null) {
            return;
        }
        if (prevPeriodStart.isAfter(now) || prevPeriodEnd.isAfter(now)) {
            Log.w(TAG, "Previous period (" + prevPeriodStart + "," + prevPeriodEnd + ") is after"
                    + " current date " + now);
            // Clock was adjusted backwards. We can continue execution though, the separation
            // and length validation below still works under this condition.
        }
        List<FreezePeriod> allPeriods = FreezePeriod.canonicalizePeriods(periods);
        // Given current time now, find the freeze period that's either current, or the one
        // that's immediately afterwards. For the later case, it might be after the year-end,
        // but this can only happen if there is only one freeze period.
        FreezePeriod curOrNextFreezePeriod = allPeriods.get(0);
        for (FreezePeriod interval : allPeriods) {
            if (interval.contains(now)
                    || interval.mStartDay > FreezePeriod.dayOfYearDisregardLeapYear(now)) {
                curOrNextFreezePeriod = interval;
                break;
            }
        }
        Pair<LocalDate, LocalDate> curOrNextFreezeDates = curOrNextFreezePeriod
                .toCurrentOrFutureRealDates(now);
        if (now.isAfter(curOrNextFreezeDates.first)) {
            curOrNextFreezeDates = new Pair<>(now, curOrNextFreezeDates.second);
        }
        if (curOrNextFreezeDates.first.isAfter(curOrNextFreezeDates.second)) {
            throw new IllegalStateException("Current freeze dates inverted: "
                    + curOrNextFreezeDates.first + "-" + curOrNextFreezeDates.second);
        }
        // Now validate [prevPeriodStart, prevPeriodEnd] against curOrNextFreezeDates
        final String periodsDescription = "Prev: " + prevPeriodStart + "," + prevPeriodEnd
                + "; cur: " + curOrNextFreezeDates.first + "," + curOrNextFreezeDates.second;
        long separation = FreezePeriod.distanceWithoutLeapYear(curOrNextFreezeDates.first,
                prevPeriodEnd) - 1;
        if (separation > 0) {
            // Two intervals do not overlap, check separation
            if (separation < SystemUpdatePolicy.FREEZE_PERIOD_MIN_SEPARATION) {
                throw ValidationFailedException.combinedPeriodTooClose("Previous freeze period "
                        + "too close to new period: " + separation + ", " + periodsDescription);
            }
        } else {
            // Two intervals overlap, check combined length
            long length = FreezePeriod.distanceWithoutLeapYear(curOrNextFreezeDates.second,
                    prevPeriodStart) + 1;
            if (length > SystemUpdatePolicy.FREEZE_PERIOD_MAX_LENGTH) {
                throw ValidationFailedException.combinedPeriodTooLong("Combined freeze period "
                        + "exceeds maximum days: " + length + ", " + periodsDescription);
            }
        }
    }
}
