// 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.index.change;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.stream.Collectors.joining;

import com.google.auto.value.AutoValue;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.MultimapBuilder;
import com.google.common.collect.SetMultimap;
import com.google.common.collect.Sets;
import com.google.common.collect.Streams;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.extensions.restapi.Url;
import com.google.gerrit.index.IndexConfig;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.index.RefState;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.regex.Pattern;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Singleton
public class StalenessChecker {
  private static final Logger log = LoggerFactory.getLogger(StalenessChecker.class);

  public static final ImmutableSet<String> FIELDS =
      ImmutableSet.of(
          ChangeField.CHANGE.getName(),
          ChangeField.REF_STATE.getName(),
          ChangeField.REF_STATE_PATTERN.getName());

  private final ChangeIndexCollection indexes;
  private final GitRepositoryManager repoManager;
  private final IndexConfig indexConfig;
  private final Provider<ReviewDb> db;

  @Inject
  StalenessChecker(
      ChangeIndexCollection indexes,
      GitRepositoryManager repoManager,
      IndexConfig indexConfig,
      Provider<ReviewDb> db) {
    this.indexes = indexes;
    this.repoManager = repoManager;
    this.indexConfig = indexConfig;
    this.db = db;
  }

  public boolean isStale(Change.Id id) throws IOException, OrmException {
    ChangeIndex i = indexes.getSearchIndex();
    if (i == null) {
      return false; // No index; caller couldn't do anything if it is stale.
    }
    if (!i.getSchema().hasField(ChangeField.REF_STATE)
        || !i.getSchema().hasField(ChangeField.REF_STATE_PATTERN)) {
      return false; // Index version not new enough for this check.
    }

    Optional<ChangeData> result =
        i.get(id, IndexedChangeQuery.createOptions(indexConfig, 0, 1, FIELDS));
    if (!result.isPresent()) {
      return true; // Not in index, but caller wants it to be.
    }
    ChangeData cd = result.get();
    return isStale(
        repoManager,
        id,
        cd.change(),
        ChangeNotes.readOneReviewDbChange(db.get(), id),
        parseStates(cd),
        parsePatterns(cd));
  }

  public static boolean isStale(
      GitRepositoryManager repoManager,
      Change.Id id,
      Change indexChange,
      @Nullable Change reviewDbChange,
      SetMultimap<Project.NameKey, RefState> states,
      ListMultimap<Project.NameKey, RefStatePattern> patterns) {
    return reviewDbChangeIsStale(indexChange, reviewDbChange)
        || refsAreStale(repoManager, id, states, patterns);
  }

  @VisibleForTesting
  static boolean refsAreStale(
      GitRepositoryManager repoManager,
      Change.Id id,
      SetMultimap<Project.NameKey, RefState> states,
      ListMultimap<Project.NameKey, RefStatePattern> patterns) {
    Set<Project.NameKey> projects = Sets.union(states.keySet(), patterns.keySet());

    for (Project.NameKey p : projects) {
      if (refsAreStale(repoManager, id, p, states, patterns)) {
        return true;
      }
    }

    return false;
  }

  @VisibleForTesting
  static boolean reviewDbChangeIsStale(Change indexChange, @Nullable Change reviewDbChange) {
    checkNotNull(indexChange);
    PrimaryStorage storageFromIndex = PrimaryStorage.of(indexChange);
    PrimaryStorage storageFromReviewDb = PrimaryStorage.of(reviewDbChange);
    if (reviewDbChange == null) {
      if (storageFromIndex == PrimaryStorage.REVIEW_DB) {
        return true; // Index says it should have been in ReviewDb, but it wasn't.
      }
      return false; // Not in ReviewDb, but that's ok.
    }
    checkArgument(
        indexChange.getId().equals(reviewDbChange.getId()),
        "mismatched change ID: %s != %s",
        indexChange.getId(),
        reviewDbChange.getId());
    if (storageFromIndex != storageFromReviewDb) {
      return true; // Primary storage differs, definitely stale.
    }
    if (storageFromReviewDb != PrimaryStorage.REVIEW_DB) {
      return false; // Not a ReviewDb change, don't check rowVersion.
    }
    return reviewDbChange.getRowVersion() != indexChange.getRowVersion();
  }

  private SetMultimap<Project.NameKey, RefState> parseStates(ChangeData cd) {
    return parseStates(cd.getRefStates());
  }

  public static SetMultimap<Project.NameKey, RefState> parseStates(Iterable<byte[]> states) {
    RefState.check(states != null, null);
    SetMultimap<Project.NameKey, RefState> result =
        MultimapBuilder.hashKeys().hashSetValues().build();
    for (byte[] b : states) {
      RefState.check(b != null, null);
      String s = new String(b, UTF_8);
      List<String> parts = Splitter.on(':').splitToList(s);
      RefState.check(parts.size() == 3 && !parts.get(0).isEmpty() && !parts.get(1).isEmpty(), s);
      result.put(new Project.NameKey(parts.get(0)), RefState.create(parts.get(1), parts.get(2)));
    }
    return result;
  }

  private ListMultimap<Project.NameKey, RefStatePattern> parsePatterns(ChangeData cd) {
    return parsePatterns(cd.getRefStatePatterns());
  }

  public static ListMultimap<Project.NameKey, RefStatePattern> parsePatterns(
      Iterable<byte[]> patterns) {
    RefStatePattern.check(patterns != null, null);
    ListMultimap<Project.NameKey, RefStatePattern> result =
        MultimapBuilder.hashKeys().arrayListValues().build();
    for (byte[] b : patterns) {
      RefStatePattern.check(b != null, null);
      String s = new String(b, UTF_8);
      List<String> parts = Splitter.on(':').splitToList(s);
      RefStatePattern.check(parts.size() == 2, s);
      result.put(
          new Project.NameKey(Url.decode(parts.get(0))), RefStatePattern.create(parts.get(1)));
    }
    return result;
  }

  private static boolean refsAreStale(
      GitRepositoryManager repoManager,
      Change.Id id,
      Project.NameKey project,
      SetMultimap<Project.NameKey, RefState> allStates,
      ListMultimap<Project.NameKey, RefStatePattern> allPatterns) {
    try (Repository repo = repoManager.openRepository(project)) {
      Set<RefState> states = allStates.get(project);
      for (RefState state : states) {
        if (!state.match(repo)) {
          return true;
        }
      }
      for (RefStatePattern pattern : allPatterns.get(project)) {
        if (!pattern.match(repo, states)) {
          return true;
        }
      }
      return false;
    } catch (IOException e) {
      log.warn("error checking staleness of {} in {}", id, project, e);
      return true;
    }
  }

  /**
   * Pattern for matching refs.
   *
   * <p>Similar to '*' syntax for native Git refspecs, but slightly more powerful: the pattern may
   * contain arbitrarily many asterisks. There must be at least one '*' and the first one must
   * immediately follow a '/'.
   */
  @AutoValue
  public abstract static class RefStatePattern {
    static RefStatePattern create(String pattern) {
      int star = pattern.indexOf('*');
      check(star > 0 && pattern.charAt(star - 1) == '/', pattern);
      String prefix = pattern.substring(0, star);
      check(Repository.isValidRefName(pattern.replace('*', 'x')), pattern);

      // Quote everything except the '*'s, which become ".*".
      String regex =
          Streams.stream(Splitter.on('*').split(pattern))
              .map(Pattern::quote)
              .collect(joining(".*", "^", "$"));
      return new AutoValue_StalenessChecker_RefStatePattern(
          pattern, prefix, Pattern.compile(regex));
    }

    byte[] toByteArray(Project.NameKey project) {
      return (project.toString() + ':' + pattern()).getBytes(UTF_8);
    }

    private static void check(boolean condition, String str) {
      checkArgument(condition, "invalid RefStatePattern: %s", str);
    }

    abstract String pattern();

    abstract String prefix();

    abstract Pattern regex();

    boolean match(String refName) {
      return regex().matcher(refName).find();
    }

    private boolean match(Repository repo, Set<RefState> expected) throws IOException {
      for (Ref r : repo.getRefDatabase().getRefs(prefix()).values()) {
        if (!match(r.getName())) {
          continue;
        }
        if (!expected.contains(RefState.of(r))) {
          return false;
        }
      }
      return true;
    }
  }
}
