// Copyright (C) 2017 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.group;

import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.gerrit.server.git.QueueProvider.QueueType.BATCH;

import com.google.common.base.Stopwatch;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.gerrit.index.SiteIndexer;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.group.Groups;
import com.google.gerrit.server.group.InternalGroup;
import com.google.gerrit.server.index.IndexExecutor;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.SchemaFactory;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.lib.TextProgressMonitor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Singleton
public class AllGroupsIndexer extends SiteIndexer<AccountGroup.UUID, InternalGroup, GroupIndex> {
  private static final Logger log = LoggerFactory.getLogger(AllGroupsIndexer.class);

  private final SchemaFactory<ReviewDb> schemaFactory;
  private final ListeningExecutorService executor;
  private final GroupCache groupCache;
  private final Groups groups;

  @Inject
  AllGroupsIndexer(
      SchemaFactory<ReviewDb> schemaFactory,
      @IndexExecutor(BATCH) ListeningExecutorService executor,
      GroupCache groupCache,
      Groups groups) {
    this.schemaFactory = schemaFactory;
    this.executor = executor;
    this.groupCache = groupCache;
    this.groups = groups;
  }

  @Override
  public SiteIndexer.Result indexAll(GroupIndex index) {
    ProgressMonitor progress = new TextProgressMonitor(new PrintWriter(progressOut));
    progress.start(2);
    Stopwatch sw = Stopwatch.createStarted();
    List<AccountGroup.UUID> uuids;
    try {
      uuids = collectGroups(progress);
    } catch (OrmException e) {
      log.error("Error collecting groups", e);
      return new SiteIndexer.Result(sw, false, 0, 0);
    }
    return reindexGroups(index, uuids, progress);
  }

  private SiteIndexer.Result reindexGroups(
      GroupIndex index, List<AccountGroup.UUID> uuids, ProgressMonitor progress) {
    progress.beginTask("Reindexing groups", uuids.size());
    List<ListenableFuture<?>> futures = new ArrayList<>(uuids.size());
    AtomicBoolean ok = new AtomicBoolean(true);
    AtomicInteger done = new AtomicInteger();
    AtomicInteger failed = new AtomicInteger();
    Stopwatch sw = Stopwatch.createStarted();
    for (AccountGroup.UUID uuid : uuids) {
      String desc = "group " + uuid;
      ListenableFuture<?> future =
          executor.submit(
              () -> {
                try {
                  Optional<InternalGroup> oldGroup = groupCache.get(uuid);
                  if (oldGroup.isPresent()) {
                    InternalGroup group = oldGroup.get();
                    groupCache.evict(group.getGroupUUID(), group.getId(), group.getNameKey());
                  }
                  Optional<InternalGroup> internalGroup = groupCache.get(uuid);
                  if (internalGroup.isPresent()) {
                    index.replace(internalGroup.get());
                  } else {
                    index.delete(uuid);
                  }
                  verboseWriter.println("Reindexed " + desc);
                  done.incrementAndGet();
                } catch (Exception e) {
                  failed.incrementAndGet();
                  throw e;
                }
                return null;
              });
      addErrorListener(future, desc, progress, ok);
      futures.add(future);
    }

    try {
      Futures.successfulAsList(futures).get();
    } catch (ExecutionException | InterruptedException e) {
      log.error("Error waiting on group futures", e);
      return new SiteIndexer.Result(sw, false, 0, 0);
    }

    progress.endTask();
    return new SiteIndexer.Result(sw, ok.get(), done.get(), failed.get());
  }

  private List<AccountGroup.UUID> collectGroups(ProgressMonitor progress) throws OrmException {
    progress.beginTask("Collecting groups", ProgressMonitor.UNKNOWN);
    try (ReviewDb db = schemaFactory.open()) {
      return groups.getAll(db).map(AccountGroup::getGroupUUID).collect(toImmutableList());
    } finally {
      progress.endTask();
    }
  }
}
