// Copyright (C) 2016 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.account;

import static com.google.common.base.MoreObjects.firstNonNull;
import static java.util.Objects.requireNonNull;

import com.google.auto.value.AutoValue;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Enums;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.MultimapBuilder;
import com.google.common.collect.Sets;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.NotifyConfig;
import com.google.gerrit.entities.Project;
import com.google.gerrit.server.git.ValidationError;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.jgit.lib.Config;

/**
 * Parses/writes project watches from/to a {@link Config} file.
 *
 * <p>This is a low-level API. Read/write of project watches in a user branch should be done through
 * {@link AccountsUpdate} or {@link AccountConfig}.
 *
 * <p>The config file has one 'project' section for all project watches of a project.
 *
 * <p>The project name is used as subsection name and the filters with the notify types that decide
 * for which events email notifications should be sent are represented as 'notify' values in the
 * subsection. A 'notify' value is formatted as {@code <filter>
 * [<comma-separated-list-of-notify-types>]}:
 *
 * <pre>
 *   [project "foo"]
 *     notify = * [ALL_COMMENTS]
 *     notify = branch:master [ALL_COMMENTS, NEW_PATCHSETS]
 *     notify = branch:master owner:self [SUBMITTED_CHANGES]
 * </pre>
 *
 * <p>If two notify values in the same subsection have the same filter they are merged on the next
 * save, taking the union of the notify types.
 *
 * <p>For watch configurations that notify on no event the list of notify types is empty:
 *
 * <pre>
 *   [project "foo"]
 *     notify = branch:master []
 * </pre>
 *
 * <p>Unknown notify types are ignored and removed on save.
 *
 * <p>The project watches are lazily parsed.
 */
public class ProjectWatches {
  @AutoValue
  public abstract static class ProjectWatchKey {

    public static ProjectWatchKey create(Project.NameKey project, @Nullable String filter) {
      return new AutoValue_ProjectWatches_ProjectWatchKey(project, Strings.emptyToNull(filter));
    }

    public abstract Project.NameKey project();

    public abstract @Nullable String filter();
  }

  public static final String FILTER_ALL = "*";

  public static final String WATCH_CONFIG = "watch.config";
  public static final String PROJECT = "project";
  public static final String KEY_NOTIFY = "notify";

  private final Account.Id accountId;
  private final Config cfg;
  private final ValidationError.Sink validationErrorSink;

  private ImmutableMap<ProjectWatchKey, ImmutableSet<NotifyConfig.NotifyType>> projectWatches;

  ProjectWatches(Account.Id accountId, Config cfg, ValidationError.Sink validationErrorSink) {
    this.accountId = requireNonNull(accountId, "accountId");
    this.cfg = requireNonNull(cfg, "cfg");
    this.validationErrorSink = requireNonNull(validationErrorSink, "validationErrorSink");
  }

  public ImmutableMap<ProjectWatchKey, ImmutableSet<NotifyConfig.NotifyType>> getProjectWatches() {
    if (projectWatches == null) {
      parse();
    }
    return projectWatches;
  }

  public void parse() {
    projectWatches = parse(accountId, cfg, validationErrorSink);
  }

  /**
   * Parses project watches from the given config file and returns them as a map.
   *
   * <p>A project watch is defined on a project and has a filter to match changes for which the
   * project watch should be applied. The project and the filter form the map key. The map value is
   * a set of notify types that decide for which events email notifications should be sent.
   *
   * <p>A project watch on the {@code All-Projects} project applies for all projects unless the
   * project has a matching project watch.
   *
   * <p>A project watch can have an empty set of notify types. An empty set of notify types means
   * that no notification for matching changes should be set. This is different from no project
   * watch as it overwrites matching project watches from the {@code All-Projects} project.
   *
   * <p>Since we must be able to differentiate a project watch with an empty set of notify types
   * from no project watch we can't use a {@link Multimap} as return type.
   *
   * @param accountId the ID of the account for which the project watches should be parsed
   * @param cfg the config file from which the project watches should be parsed
   * @param validationErrorSink validation error sink
   * @return the parsed project watches
   */
  @VisibleForTesting
  public static ImmutableMap<ProjectWatchKey, ImmutableSet<NotifyConfig.NotifyType>> parse(
      Account.Id accountId, Config cfg, ValidationError.Sink validationErrorSink) {
    Map<ProjectWatchKey, Set<NotifyConfig.NotifyType>> projectWatches = new HashMap<>();
    for (String projectName : cfg.getSubsections(PROJECT)) {
      String[] notifyValues = cfg.getStringList(PROJECT, projectName, KEY_NOTIFY);
      for (String nv : notifyValues) {
        if (Strings.isNullOrEmpty(nv)) {
          continue;
        }

        NotifyValue notifyValue =
            NotifyValue.parse(accountId, projectName, nv, validationErrorSink);
        if (notifyValue == null) {
          continue;
        }

        ProjectWatchKey key =
            ProjectWatchKey.create(Project.nameKey(projectName), notifyValue.filter());
        if (!projectWatches.containsKey(key)) {
          projectWatches.put(key, EnumSet.noneOf(NotifyConfig.NotifyType.class));
        }
        projectWatches.get(key).addAll(notifyValue.notifyTypes());
      }
    }
    return immutableCopyOf(projectWatches);
  }

  public Config save(Map<ProjectWatchKey, Set<NotifyConfig.NotifyType>> projectWatches) {
    this.projectWatches = immutableCopyOf(projectWatches);

    for (String projectName : cfg.getSubsections(PROJECT)) {
      cfg.unsetSection(PROJECT, projectName);
    }

    ListMultimap<String, String> notifyValuesByProject =
        MultimapBuilder.hashKeys().arrayListValues().build();
    for (Map.Entry<ProjectWatchKey, Set<NotifyConfig.NotifyType>> e : projectWatches.entrySet()) {
      NotifyValue notifyValue = NotifyValue.create(e.getKey().filter(), e.getValue());
      notifyValuesByProject.put(e.getKey().project().get(), notifyValue.toString());
    }

    for (Map.Entry<String, Collection<String>> e : notifyValuesByProject.asMap().entrySet()) {
      cfg.setStringList(PROJECT, e.getKey(), KEY_NOTIFY, new ArrayList<>(e.getValue()));
    }

    return cfg;
  }

  private static ImmutableMap<ProjectWatchKey, ImmutableSet<NotifyConfig.NotifyType>>
      immutableCopyOf(Map<ProjectWatchKey, Set<NotifyConfig.NotifyType>> projectWatches) {
    ImmutableMap.Builder<ProjectWatchKey, ImmutableSet<NotifyConfig.NotifyType>> b =
        ImmutableMap.builder();
    projectWatches.entrySet().stream()
        .forEach(e -> b.put(e.getKey(), ImmutableSet.copyOf(e.getValue())));
    return b.build();
  }

  @AutoValue
  public abstract static class NotifyValue {
    public static NotifyValue parse(
        Account.Id accountId,
        String project,
        String notifyValue,
        ValidationError.Sink validationErrorSink) {
      notifyValue = notifyValue.trim();
      int i = notifyValue.lastIndexOf('[');
      if (i < 0 || notifyValue.charAt(notifyValue.length() - 1) != ']') {
        validationErrorSink.error(
            ValidationError.create(
                WATCH_CONFIG,
                String.format(
                    "Invalid project watch of account %d for project %s: %s",
                    accountId.get(), project, notifyValue)));
        return null;
      }
      String filter = notifyValue.substring(0, i).trim();
      if (filter.isEmpty() || FILTER_ALL.equals(filter)) {
        filter = null;
      }

      Set<NotifyConfig.NotifyType> notifyTypes = EnumSet.noneOf(NotifyConfig.NotifyType.class);
      if (i + 1 < notifyValue.length() - 2) {
        for (String nt :
            Splitter.on(',')
                .trimResults()
                .splitToList(notifyValue.substring(i + 1, notifyValue.length() - 1))) {
          NotifyConfig.NotifyType notifyType =
              Enums.getIfPresent(NotifyConfig.NotifyType.class, nt).orNull();
          if (notifyType == null) {
            validationErrorSink.error(
                ValidationError.create(
                    WATCH_CONFIG,
                    String.format(
                        "Invalid notify type %s in project watch "
                            + "of account %d for project %s: %s",
                        nt, accountId.get(), project, notifyValue)));
            continue;
          }
          notifyTypes.add(notifyType);
        }
      }
      return create(filter, notifyTypes);
    }

    public static NotifyValue create(
        @Nullable String filter, Collection<NotifyConfig.NotifyType> notifyTypes) {
      return new AutoValue_ProjectWatches_NotifyValue(
          Strings.emptyToNull(filter), Sets.immutableEnumSet(notifyTypes));
    }

    public abstract @Nullable String filter();

    public abstract ImmutableSet<NotifyConfig.NotifyType> notifyTypes();

    @Override
    public final String toString() {
      List<NotifyConfig.NotifyType> notifyTypes = new ArrayList<>(notifyTypes());
      StringBuilder notifyValue = new StringBuilder();
      notifyValue.append(firstNonNull(filter(), FILTER_ALL)).append(" [");
      Joiner.on(", ").appendTo(notifyValue, notifyTypes);
      notifyValue.append("]");
      return notifyValue.toString();
    }
  }
}
