// 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 com.google.common.collect.ImmutableSet;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.git.RefUpdateUtil;
import com.google.gerrit.metrics.MetricMaker;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.CurrentSchemaVersion;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.Sequences;
import com.google.gerrit.server.account.GroupUUID;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.GerritServerId;
import com.google.gerrit.server.config.SitePath;
import com.google.gerrit.server.config.SitePaths;
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.InternalGroup;
import com.google.gerrit.server.group.db.AuditLogFormatter;
import com.google.gerrit.server.group.db.GroupConfig;
import com.google.gerrit.server.group.db.GroupNameNotes;
import com.google.gerrit.server.group.db.InternalGroupCreation;
import com.google.gerrit.server.group.db.InternalGroupUpdate;
import com.google.gerrit.server.index.group.GroupIndex;
import com.google.gerrit.server.index.group.GroupIndexCollection;
import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gwtorm.jdbc.JdbcExecutor;
import com.google.gwtorm.jdbc.JdbcSchema;
import com.google.gwtorm.server.OrmDuplicateKeyException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Collections;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;

/** Creates the current database schema and populates initial code rows. */
public class ReviewDbSchemaCreator {
  @SitePath private final Path site_path;

  private final GitRepositoryManager repoManager;
  private final AllProjectsCreator allProjectsCreator;
  private final AllUsersCreator allUsersCreator;
  private final AllUsersName allUsersName;
  private final PersonIdent serverUser;
  private final DataSourceType dataSourceType;
  private final GroupIndexCollection indexCollection;
  private final String serverId;

  private final Config config;
  private final MetricMaker metricMaker;
  private final NotesMigration migration;
  private final AllProjectsName allProjectsName;

  @Inject
  public ReviewDbSchemaCreator(
      SitePaths site,
      GitRepositoryManager repoManager,
      AllProjectsCreator ap,
      AllUsersCreator auc,
      AllUsersName allUsersName,
      @GerritPersonIdent PersonIdent au,
      DataSourceType dst,
      GroupIndexCollection ic,
      @GerritServerId String serverId,
      @GerritServerConfig Config config,
      MetricMaker metricMaker,
      NotesMigration migration,
      AllProjectsName apName) {
    this(
        site.site_path,
        repoManager,
        ap,
        auc,
        allUsersName,
        au,
        dst,
        ic,
        serverId,
        config,
        metricMaker,
        migration,
        apName);
  }

  public ReviewDbSchemaCreator(
      @SitePath Path site,
      GitRepositoryManager repoManager,
      AllProjectsCreator ap,
      AllUsersCreator auc,
      AllUsersName allUsersName,
      @GerritPersonIdent PersonIdent au,
      DataSourceType dst,
      GroupIndexCollection ic,
      String serverId,
      Config config,
      MetricMaker metricMaker,
      NotesMigration migration,
      AllProjectsName apName) {
    site_path = site;
    this.repoManager = repoManager;
    allProjectsCreator = ap;
    allUsersCreator = auc;
    this.allUsersName = allUsersName;
    serverUser = au;
    dataSourceType = dst;
    indexCollection = ic;
    this.serverId = serverId;

    this.config = config;
    this.allProjectsName = apName;
    this.migration = migration;
    this.metricMaker = metricMaker;
  }

  public void create(ReviewDb db) throws OrmException, IOException, ConfigInvalidException {
    final JdbcSchema jdbc = (JdbcSchema) db;
    try (JdbcExecutor e = new JdbcExecutor(jdbc)) {
      jdbc.updateSchema(e);
    }

    final CurrentSchemaVersion sVer = CurrentSchemaVersion.create();
    sVer.versionNbr = ReviewDbSchemaVersion.getBinaryVersion();
    db.schemaVersion().insert(Collections.singleton(sVer));

    GroupReference admins = createGroupReference("Administrators");
    GroupReference batchUsers = createGroupReference("Non-Interactive Users");

    allProjectsCreator.setAdministrators(admins).setBatchUsers(batchUsers).create();
    // We have to create the All-Users repository before we can use it to store the groups in it.
    allUsersCreator.setAdministrators(admins).create();

    // Don't rely on injection to construct Sequences, as it requires ReviewDb.
    Sequences seqs =
        new Sequences(
            config,
            () -> db,
            migration,
            repoManager,
            GitReferenceUpdated.DISABLED,
            allProjectsName,
            allUsersName,
            metricMaker);
    try (Repository allUsersRepo = repoManager.openRepository(allUsersName)) {
      createAdminsGroup(seqs, allUsersRepo, admins);
      createBatchUsersGroup(seqs, allUsersRepo, batchUsers, admins.getUUID());
    }

    dataSourceType.getIndexScript().run(db);
  }

  private void createAdminsGroup(
      Sequences seqs, Repository allUsersRepo, GroupReference groupReference)
      throws OrmException, IOException, ConfigInvalidException {
    InternalGroupCreation groupCreation = getGroupCreation(seqs, groupReference);
    InternalGroupUpdate groupUpdate =
        InternalGroupUpdate.builder().setDescription("Gerrit Site Administrators").build();

    createGroup(allUsersRepo, groupCreation, groupUpdate);
  }

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

    createGroup(allUsersRepo, groupCreation, groupUpdate);
  }

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

  private InternalGroup createGroupInNoteDb(
      Repository allUsersRepo, InternalGroupCreation groupCreation, InternalGroupUpdate groupUpdate)
      throws ConfigInvalidException, IOException, OrmDuplicateKeyException {
    // 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.setGroupUpdate(groupUpdate, auditLogFormatter);

    AccountGroup.NameKey groupName = groupUpdate.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) throws IOException {
    for (GroupIndex groupIndex : indexCollection.getWriteIndexes()) {
      groupIndex.replace(group);
    }
  }

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

  private InternalGroupCreation getGroupCreation(Sequences seqs, GroupReference groupReference)
      throws OrmException {
    int next = seqs.nextGroupId();
    return InternalGroupCreation.builder()
        .setNameKey(new AccountGroup.NameKey(groupReference.getName()))
        .setId(new AccountGroup.Id(next))
        .setGroupUUID(groupReference.getUUID())
        .build();
  }
}
