// Copyright (C) 2009 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.schema;

import static com.google.gerrit.server.Sequence.LightweightGroups;

import com.google.common.collect.ImmutableSet;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.AccountGroup;
import com.google.gerrit.entities.GroupReference;
import com.google.gerrit.entities.InternalGroup;
import com.google.gerrit.exceptions.DuplicateKeyException;
import com.google.gerrit.git.RefUpdateUtil;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.Sequence;
import com.google.gerrit.server.account.GroupUuid;
import com.google.gerrit.server.account.ServiceUserClassifier;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.meta.MetaDataUpdate;
import com.google.gerrit.server.group.db.AuditLogFormatter;
import com.google.gerrit.server.group.db.GroupConfig;
import com.google.gerrit.server.group.db.GroupDelta;
import com.google.gerrit.server.group.db.GroupNameNotes;
import com.google.gerrit.server.group.db.InternalGroupCreation;
import com.google.gerrit.server.index.group.GroupIndex;
import com.google.gerrit.server.index.group.GroupIndexCollection;
import com.google.gerrit.server.update.context.RefUpdateContext;
import com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType;
import com.google.inject.Inject;
import java.io.IOException;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;

// TODO(dborowitz): The current NoteDb implementation mirrors the old ReviewDb code: this class is
// called to create the site early on in NoteDbSchemaUpdater#update. This logic is a little
// confusing and could stand to be reworked. Another smell is that this is an interface only for
// testing purposes.
public class SchemaCreatorImpl implements SchemaCreator {
  private final GitRepositoryManager repoManager;
  private final AllProjectsCreator allProjectsCreator;
  private final AllUsersCreator allUsersCreator;
  private final AllUsersName allUsersName;
  private final Sequence groupsSequence;
  private final PersonIdent serverUser;
  private final GroupIndexCollection indexCollection;
  private final String serverId;
  private final AllProjectsName allProjectsName;

  @Inject
  public SchemaCreatorImpl(
      GitRepositoryManager repoManager,
      AllProjectsCreator ap,
      AllUsersCreator auc,
      AllUsersName allUsersName,
      @LightweightGroups Sequence groupsSequence,
      @GerritPersonIdent PersonIdent au,
      GroupIndexCollection ic,
      String serverId,
      AllProjectsName apName) {
    this.repoManager = repoManager;
    allProjectsCreator = ap;
    allUsersCreator = auc;
    this.allUsersName = allUsersName;
    this.groupsSequence = groupsSequence;
    serverUser = au;
    indexCollection = ic;
    this.serverId = serverId;

    this.allProjectsName = apName;
  }

  @Override
  public void create() throws IOException, ConfigInvalidException {
    try (RefUpdateContext ctx = RefUpdateContext.open(RefUpdateType.INIT_REPO)) {
      GroupReference admins = createGroupReference("Administrators");
      GroupReference serviceUsers = createGroupReference(ServiceUserClassifier.SERVICE_USERS);

      AllProjectsInput allProjectsInput =
          AllProjectsInput.builder()
              .administratorsGroup(admins)
              .serviceUsersGroup(serviceUsers)
              .build();
      allProjectsCreator.create(allProjectsInput);
      // We have to create the All-Users repository before we can use it to store the groups in it.
      allUsersCreator.setAdministrators(admins).create();

      try (Repository allUsersRepo = repoManager.openRepository(allUsersName)) {
        createAdminsGroup(allUsersRepo, admins);
        createBatchUsersGroup(allUsersRepo, serviceUsers, admins.getUUID());
      }
    }
  }

  @Override
  public void ensureCreated() throws IOException, ConfigInvalidException {
    try {
      repoManager.openRepository(allProjectsName).close();
    } catch (RepositoryNotFoundException e) {
      create();
    }
  }

  private void createAdminsGroup(Repository allUsersRepo, GroupReference groupReference)
      throws IOException, ConfigInvalidException {
    InternalGroupCreation groupCreation = getGroupCreation(groupReference);
    GroupDelta groupDelta =
        GroupDelta.builder().setDescription("Gerrit Site Administrators").build();

    createGroup(allUsersRepo, groupCreation, groupDelta);
  }

  private void createBatchUsersGroup(
      Repository allUsersRepo, GroupReference groupReference, AccountGroup.UUID adminsGroupUuid)
      throws IOException, ConfigInvalidException {
    InternalGroupCreation groupCreation = getGroupCreation(groupReference);
    GroupDelta groupDelta =
        GroupDelta.builder()
            .setDescription("Users who perform batch actions on Gerrit")
            .setOwnerGroupUUID(adminsGroupUuid)
            .build();

    createGroup(allUsersRepo, groupCreation, groupDelta);
  }

  private void createGroup(
      Repository allUsersRepo, InternalGroupCreation groupCreation, GroupDelta groupDelta)
      throws ConfigInvalidException, IOException {
    InternalGroup createdGroup = createGroupInNoteDb(allUsersRepo, groupCreation, groupDelta);
    index(createdGroup);
  }

  private InternalGroup createGroupInNoteDb(
      Repository allUsersRepo, InternalGroupCreation groupCreation, GroupDelta groupDelta)
      throws ConfigInvalidException, IOException, DuplicateKeyException {
    // This method is only executed on a new server which doesn't have any accounts or groups.
    AuditLogFormatter auditLogFormatter =
        AuditLogFormatter.createBackedBy(ImmutableSet.of(), ImmutableSet.of(), serverId);

    GroupConfig groupConfig =
        GroupConfig.createForNewGroup(allUsersName, allUsersRepo, groupCreation);
    groupConfig.setGroupDelta(groupDelta, auditLogFormatter);

    AccountGroup.NameKey groupName = groupDelta.getName().orElseGet(groupCreation::getNameKey);
    GroupNameNotes groupNameNotes =
        GroupNameNotes.forNewGroup(
            allUsersName, allUsersRepo, groupCreation.getGroupUUID(), groupName);

    commit(allUsersRepo, groupConfig, groupNameNotes);

    return groupConfig
        .getLoadedGroup()
        .orElseThrow(() -> new IllegalStateException("Created group wasn't automatically loaded"));
  }

  private void commit(
      Repository allUsersRepo, GroupConfig groupConfig, GroupNameNotes groupNameNotes)
      throws IOException {
    BatchRefUpdate batchRefUpdate = allUsersRepo.getRefDatabase().newBatchUpdate();
    try (MetaDataUpdate metaDataUpdate = createMetaDataUpdate(allUsersRepo, batchRefUpdate)) {
      groupConfig.commit(metaDataUpdate);
    }
    // MetaDataUpdates unfortunately can't be reused. -> Create a new one.
    try (MetaDataUpdate metaDataUpdate = createMetaDataUpdate(allUsersRepo, batchRefUpdate)) {
      groupNameNotes.commit(metaDataUpdate);
    }
    RefUpdateUtil.executeChecked(batchRefUpdate, allUsersRepo);
  }

  private MetaDataUpdate createMetaDataUpdate(
      Repository allUsersRepo, @Nullable BatchRefUpdate batchRefUpdate) {
    MetaDataUpdate metaDataUpdate =
        new MetaDataUpdate(
            GitReferenceUpdated.DISABLED, allUsersName, allUsersRepo, batchRefUpdate);
    metaDataUpdate.getCommitBuilder().setAuthor(serverUser);
    metaDataUpdate.getCommitBuilder().setCommitter(serverUser);
    return metaDataUpdate;
  }

  private void index(InternalGroup group) {
    for (GroupIndex groupIndex : indexCollection.getWriteIndexes()) {
      groupIndex.replace(group);
    }
  }

  private GroupReference createGroupReference(String name) {
    AccountGroup.UUID groupUuid = GroupUuid.make(name, serverUser);
    return GroupReference.create(groupUuid, name);
  }

  private InternalGroupCreation getGroupCreation(GroupReference groupReference) {
    int next = groupsSequence.next();
    return InternalGroupCreation.builder()
        .setNameKey(AccountGroup.nameKey(groupReference.getName()))
        .setId(AccountGroup.id(next))
        .setGroupUUID(groupReference.getUUID())
        .build();
  }
}
