// Copyright (C) 2014 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.google.gerrit.server.config;

import static java.time.ZoneId.systemDefault;
import static java.util.Objects.requireNonNull;

import com.google.auto.value.AutoValue;
import com.google.auto.value.extension.memoized.Memoized;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import java.time.DayOfWeek;
import java.time.Duration;
import java.time.LocalTime;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoUnit;
import java.util.Locale;
import java.util.Optional;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import org.eclipse.jgit.lib.Config;

/**
 * This class reads a schedule for running a periodic background job from a Git config.
 *
 * <p>A schedule configuration consists of the following parameters:
 *
 * <ul>
 *   <li>{@code interval}: Interval for running the periodic background job. The interval must be
 *       larger than zero. The following suffixes are supported to define the time unit for the
 *       interval:
 *       <ul>
 *         <li>{@code s}, {@code sec}, {@code second}, {@code seconds}
 *         <li>{@code m}, {@code min}, {@code minute}, {@code minutes}
 *         <li>{@code h}, {@code hr}, {@code hour}, {@code hours}
 *         <li>{@code d}, {@code day}, {@code days}
 *         <li>{@code w}, {@code week}, {@code weeks} ({@code 1 week} is treated as {@code 7 days})
 *         <li>{@code mon}, {@code month}, {@code months} ({@code 1 month} is treated as {@code 30
 *             days})
 *         <li>{@code y}, {@code year}, {@code years} ({@code 1 year} is treated as {@code 365
 *             days})
 *       </ul>
 *   <li>{@code startTime}: The start time defines the first execution of the periodic background
 *       job. If the configured {@code interval} is shorter than {@code startTime - now} the start
 *       time will be preponed by the maximum integral multiple of {@code interval} so that the
 *       start time is still in the future. {@code startTime} must have one of the following
 *       formats:
 *       <ul>
 *         <li>{@code <day of week> <hours>:<minutes>}
 *         <li>{@code <hours>:<minutes>}
 *       </ul>
 *       The placeholders can have the following values:
 *       <ul>
 *         <li>{@code <day of week>}: {@code Mon}, {@code Tue}, {@code Wed}, {@code Thu}, {@code
 *             Fri}, {@code Sat}, {@code Sun}
 *         <li>{@code <hours>}: {@code 00}-{@code 23}
 *         <li>{@code <minutes>}: {@code 00}-{@code 59}
 *       </ul>
 *       The timezone cannot be specified but is always the system default time-zone.
 *   <li>{@code jitter}: A maximum random delay that will be added to the job's start time. If 0 or
 *       not specified, no jitter is applied.
 *       <ul>
 *         <li>The same suffixes as {@code interval} are supported for defining the time unit.
 *       </ul>
 * </ul>
 *
 * <p>The section and the subsection from which the {@code interval}, {@code startTime} and {@code
 * jitter} parameters are read can be configured.
 *
 * <p>Examples for a schedule configuration:
 *
 * <ul>
 *   <li>
 *       <pre>
 * foo.startTime = Fri 10:30
 * foo.interval  = 2 day
 * foo.jitter    = 30 min
 * </pre>
 *       Assuming that the server is started on {@code Mon 7:00} then {@code startTime - now} is
 *       {@code 4 days 3:30 hours}. This is larger than the interval hence the start time is
 *       preponed by the maximum integral multiple of the interval so that start time is still in
 *       the future, i.e. preponed by 4 days. This yields a start time of {@code Mon 10:30}. After
 *       this adjustment, a random delay between 0 and 30 minutes is added. For example, if the
 *       delay is 7 minutes, the final start time becomes {@code Mon 10:37}. Subsequent executions
 *       will occur at fixed intervals from this updated start time, such as {@code Wed 10:37},
 *       {@code Fri 10:37}, and so on.
 *   <li>
 *       <pre>
 * foo.startTime = 06:00
 * foo.interval = 1 day
 * </pre>
 *       Assuming that the server is started on {@code Mon 7:00} then this yields the first run on
 *       next Tuesday at 6:00 and a repetition interval of 1 day.
 * </ul>
 */
@AutoValue
public abstract class ScheduleConfig {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  @VisibleForTesting static final String KEY_INTERVAL = "interval";
  @VisibleForTesting static final String KEY_STARTTIME = "startTime";
  @VisibleForTesting static final String KEY_JITTER = "jitter";

  private static final long MISSING_CONFIG = -1L;
  private static final long INVALID_CONFIG = -2L;
  public static final long DEFAULT_JITTER = 0L;

  public static Optional<Schedule> createSchedule(Config config, String section) {
    return builder(config, section).buildSchedule();
  }

  public static ScheduleConfig.Builder builder(Config config, String section) {
    return new AutoValue_ScheduleConfig.Builder()
        .setNow(computeNow())
        .setKeyInterval(KEY_INTERVAL)
        .setKeyStartTime(KEY_STARTTIME)
        .setKeyJitter(KEY_JITTER)
        .setConfig(config)
        .setSection(section);
  }

  abstract Config config();

  abstract String section();

  @Nullable
  abstract String subsection();

  abstract String keyInterval();

  abstract String keyStartTime();

  abstract String keyJitter();

  abstract ZonedDateTime now();

  @Memoized
  public Optional<Schedule> schedule() {
    long interval = computeInterval(config(), section(), subsection(), keyInterval());
    long jitter = computeJitter(config(), section(), subsection(), keyJitter());

    long initialDelay;
    if (interval > 0) {
      initialDelay =
          computeInitialDelay(
              config(), section(), subsection(), keyStartTime(), now(), interval, jitter);
    } else {
      initialDelay = interval;
    }

    if (isInvalidOrMissing(interval, initialDelay, jitter)) {
      return Optional.empty();
    }

    return Optional.of(Schedule.create(interval, initialDelay));
  }

  private boolean isInvalidOrMissing(long interval, long initialDelay, long jitter) {
    String key = section() + (subsection() != null ? "." + subsection() : "");
    if (interval == MISSING_CONFIG && initialDelay == MISSING_CONFIG) {
      logger.atInfo().log("No schedule configuration for \"%s\".", key);
      return true;
    }

    if (interval == MISSING_CONFIG) {
      logger.atSevere().log(
          "Incomplete schedule configuration for \"%s\" is ignored. Missing value for \"%s\".",
          key, key + "." + keyInterval());
      return true;
    }

    if (initialDelay == MISSING_CONFIG) {
      logger.atSevere().log(
          "Incomplete schedule configuration for \"%s\" is ignored. Missing value for \"%s\".",
          key, key + "." + keyStartTime());
      return true;
    }

    if (interval != INVALID_CONFIG && interval <= 0) {
      logger.atSevere().log("Invalid interval value \"%d\" for \"%s\": must be > 0", interval, key);
      interval = INVALID_CONFIG;
    }

    if (initialDelay != INVALID_CONFIG && initialDelay < 0) {
      logger.atSevere().log(
          "Invalid initial delay value \"%d\" for \"%s\": must be >= 0", initialDelay, key);
      initialDelay = INVALID_CONFIG;
    }

    if (interval == INVALID_CONFIG || initialDelay == INVALID_CONFIG || jitter == INVALID_CONFIG) {
      logger.atSevere().log("Invalid schedule configuration for \"%s\" is ignored. ", key);
      return true;
    }

    return false;
  }

  @Override
  public final String toString() {
    StringBuilder b = new StringBuilder();
    b.append(formatValue(keyInterval()));
    b.append(", ");
    b.append(formatValue(keyStartTime()));
    return b.toString();
  }

  private String formatValue(String key) {
    StringBuilder b = new StringBuilder();
    b.append(section());
    if (subsection() != null) {
      b.append(".");
      b.append(subsection());
    }
    b.append(".");
    b.append(key);
    String value = config().getString(section(), subsection(), key);
    if (value != null) {
      b.append(" = ");
      b.append(value);
    } else {
      b.append(": NA");
    }
    return b.toString();
  }

  private static long computeInterval(
      Config rc, String section, String subsection, String keyInterval) {
    try {
      return ConfigUtil.getTimeUnit(
          rc, section, subsection, keyInterval, MISSING_CONFIG, TimeUnit.MILLISECONDS);
    } catch (IllegalArgumentException e) {
      // We only need to log the exception message; it already includes the
      // section.subsection.key and bad value.
      logger.atSevere().log("%s", e.getMessage());
      return INVALID_CONFIG;
    }
  }

  private static long computeJitter(
      Config rc, String section, String subsection, String keyJitter) {
    try {
      return ConfigUtil.getTimeUnit(
          rc, section, subsection, keyJitter, DEFAULT_JITTER, TimeUnit.MILLISECONDS);
    } catch (IllegalArgumentException e) {
      logger.atSevere().log("%s", e.getMessage());
      return INVALID_CONFIG;
    }
  }

  private static long computeInitialDelay(
      Config rc,
      String section,
      String subsection,
      String keyStartTime,
      ZonedDateTime now,
      long interval,
      long jitter) {
    String start = rc.getString(section, subsection, keyStartTime);
    if (start == null) {
      return MISSING_CONFIG;
    }
    return computeInitialDelay(interval, start, now, jitter);
  }

  private static long computeInitialDelay(long interval, String start) {
    return computeInitialDelay(interval, start, computeNow(), DEFAULT_JITTER);
  }

  private static long computeInitialDelay(
      long interval, String start, ZonedDateTime now, long jitter) {
    requireNonNull(start);

    try {
      DateTimeFormatter formatter = DateTimeFormatter.ofPattern("[E ]HH:mm").withLocale(Locale.US);
      LocalTime firstStartTime = LocalTime.parse(start, formatter);
      ZonedDateTime startTime = now.with(firstStartTime);
      try {
        DayOfWeek dayOfWeek = formatter.parse(start, DayOfWeek::from);
        startTime = startTime.with(dayOfWeek);
      } catch (DateTimeParseException ignored) {
        // Day of week is an optional parameter.
      }
      startTime = startTime.truncatedTo(ChronoUnit.MINUTES);
      long delay = Duration.between(now, startTime).toMillis();
      if (jitter > 0) {
        Random random = new Random();
        // Increment by 1 to make the upper bound inclusive of the configured value
        delay += random.nextLong(jitter + 1);
      }
      delay %= interval;
      if (delay <= 0) {
        delay += interval;
      }
      return delay;
    } catch (DateTimeParseException e) {
      logger.atSevere().log("Invalid start time: %s", e.getMessage());
      return INVALID_CONFIG;
    }
  }

  private static ZonedDateTime computeNow() {
    return ZonedDateTime.now(systemDefault());
  }

  @AutoValue.Builder
  public abstract static class Builder {
    public abstract Builder setConfig(Config config);

    public abstract Builder setSection(String section);

    public abstract Builder setSubsection(@Nullable String subsection);

    public abstract Builder setKeyInterval(String keyInterval);

    public abstract Builder setKeyStartTime(String keyStartTime);

    public abstract Builder setKeyJitter(String keyJitter);

    @VisibleForTesting
    abstract Builder setNow(ZonedDateTime now);

    abstract ScheduleConfig build();

    public Optional<Schedule> buildSchedule() {
      return build().schedule();
    }
  }

  @AutoValue
  public abstract static class Schedule {
    /** Number of milliseconds between events. */
    public abstract long interval();

    /**
     * Milliseconds between constructor invocation and first event time.
     *
     * <p>If there is any lag between the constructor invocation and queuing the object into an
     * executor the event will run later, as there is no method to adjust for the scheduling delay.
     */
    public abstract long initialDelay();

    /**
     * Creates a schedule.
     *
     * <p>{@link ScheduleConfig} defines details about which values are valid for the {@code
     * interval} and {@code startTime} parameters.
     *
     * @param interval the interval in milliseconds
     * @param startTime the start time as "{@code <day of week> <hours>:<minutes>}" or "{@code
     *     <hours>:<minutes>}"
     * @return the schedule
     * @throws IllegalArgumentException if any of the parameters is invalid
     */
    public static Schedule createOrFail(long interval, String startTime) {
      return create(interval, startTime).orElseThrow(IllegalArgumentException::new);
    }

    /**
     * Creates a schedule.
     *
     * <p>{@link ScheduleConfig} defines details about which values are valid for the {@code
     * interval} and {@code startTime} parameters.
     *
     * @param interval the interval in milliseconds
     * @param startTime the start time as "{@code <day of week> <hours>:<minutes>}" or "{@code
     *     <hours>:<minutes>}"
     * @return the schedule or {@link Optional#empty()} if any of the parameters is invalid
     */
    public static Optional<Schedule> create(long interval, String startTime) {
      long initialDelay = computeInitialDelay(interval, startTime);
      if (interval <= 0 || initialDelay < 0) {
        return Optional.empty();
      }
      return Optional.of(create(interval, initialDelay));
    }

    static Schedule create(long interval, long initialDelay) {
      return new AutoValue_ScheduleConfig_Schedule(interval, initialDelay);
    }
  }
}
