// 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 com.ericsson.gerrit.plugins.highavailability.autoreindex;

import com.ericsson.gerrit.plugins.highavailability.forwarder.ForwardedIndexGroupHandler;
import com.ericsson.gerrit.plugins.highavailability.forwarder.ForwardedIndexingHandler.Operation;
import com.ericsson.gerrit.plugins.highavailability.forwarder.rest.AbstractIndexRestApiServlet;
import com.google.common.collect.Streams;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.entities.AccountGroupByIdAudit;
import com.google.gerrit.entities.AccountGroupMemberAudit;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.group.InternalGroup;
import com.google.gerrit.server.group.db.Groups;
import com.google.gerrit.server.util.OneOffRequestContext;
import com.google.inject.Inject;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Repository;

public class GroupReindexRunnable extends ReindexRunnable<GroupReference> {

  private static final FluentLogger log = FluentLogger.forEnclosingClass();

  private final Groups groups;
  private final GitRepositoryManager repoManager;
  private final AllUsersName allUsers;
  private final ForwardedIndexGroupHandler indexer;

  @Inject
  public GroupReindexRunnable(
      ForwardedIndexGroupHandler indexer,
      IndexTs indexTs,
      OneOffRequestContext ctx,
      Groups groups,
      GitRepositoryManager repoManager,
      AllUsersName allUsers) {
    super(AbstractIndexRestApiServlet.IndexName.GROUP, indexTs, ctx);
    this.groups = groups;
    this.repoManager = repoManager;
    this.allUsers = allUsers;
    this.indexer = indexer;
  }

  @Override
  protected Iterable<GroupReference> fetchItems() throws Exception {
    return groups.getAllGroupReferences()::iterator;
  }

  @Override
  protected Optional<Timestamp> indexIfNeeded(GroupReference g, Timestamp sinceTs) {
    try {
      Optional<InternalGroup> internalGroup = groups.getGroup(g.getUUID());
      if (internalGroup.isPresent()) {
        InternalGroup group = internalGroup.get();
        Timestamp groupCreationTs = group.getCreatedOn();

        Repository allUsersRepo = repoManager.openRepository(allUsers);

        List<AccountGroupByIdAudit> subGroupMembersAud =
            groups.getSubgroupsAudit(allUsersRepo, g.getUUID());
        Stream<Timestamp> groupIdAudAddedTs =
            subGroupMembersAud.stream()
                .map(AccountGroupByIdAudit::addedOn)
                .filter(Objects::nonNull);
        Stream<Timestamp> groupIdAudRemovedTs =
            subGroupMembersAud.stream()
                .map(AccountGroupByIdAudit::removedOn)
                .filter(Optional<Timestamp>::isPresent)
                .map(Optional<Timestamp>::get);

        List<AccountGroupMemberAudit> groupMembersAud =
            groups.getMembersAudit(allUsersRepo, g.getUUID());
        Stream<Timestamp> groupMemberAudAddedTs =
            groupMembersAud.stream().map(AccountGroupMemberAudit::addedOn).filter(Objects::nonNull);
        Stream<Timestamp> groupMemberAudRemovedTs =
            groupMembersAud.stream()
                .map(AccountGroupMemberAudit::removedOn)
                .filter(Optional<Timestamp>::isPresent)
                .map(Optional<Timestamp>::get);

        Optional<Timestamp> groupLastTs =
            Streams.concat(
                    groupIdAudAddedTs,
                    groupIdAudRemovedTs,
                    groupMemberAudAddedTs,
                    groupMemberAudRemovedTs,
                    Stream.of(groupCreationTs))
                .max(Comparator.naturalOrder());

        if (groupLastTs.isPresent() && groupLastTs.get().after(sinceTs)) {
          log.atInfo().log("Index %s/%s/%s", g.getUUID(), g.getName(), groupLastTs.get());
          indexer.index(g.getUUID(), Operation.INDEX, Optional.empty());
          return groupLastTs;
        }
      }
    } catch (IOException | ConfigInvalidException e) {
      log.atSevere().withCause(e).log("Reindex failed");
    }
    return Optional.empty();
  }
}
