// 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.google.gerrit.server.schema;

import static com.google.common.collect.ImmutableList.toImmutableList;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.ImmutableSortedSet;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.notedb.Sequences;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import java.io.IOException;
import java.util.stream.IntStream;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Repository;

public class NoteDbSchemaUpdater {
  private final Config cfg;
  private final AllUsersName allUsersName;
  private final GitRepositoryManager repoManager;
  private final SchemaCreator schemaCreator;
  private final NoteDbSchemaVersionManager versionManager;
  private final NoteDbSchemaVersion.Arguments args;
  private final ImmutableSortedMap<Integer, Class<? extends NoteDbSchemaVersion>> schemaVersions;

  @Inject
  NoteDbSchemaUpdater(
      @GerritServerConfig Config cfg,
      AllUsersName allUsersName,
      GitRepositoryManager repoManager,
      SchemaCreator schemaCreator,
      NoteDbSchemaVersionManager versionManager,
      NoteDbSchemaVersion.Arguments args) {
    this(
        cfg,
        allUsersName,
        repoManager,
        schemaCreator,
        versionManager,
        args,
        NoteDbSchemaVersions.ALL);
  }

  NoteDbSchemaUpdater(
      Config cfg,
      AllUsersName allUsersName,
      GitRepositoryManager repoManager,
      SchemaCreator schemaCreator,
      NoteDbSchemaVersionManager versionManager,
      NoteDbSchemaVersion.Arguments args,
      ImmutableSortedMap<Integer, Class<? extends NoteDbSchemaVersion>> schemaVersions) {
    this.cfg = cfg;
    this.allUsersName = allUsersName;
    this.repoManager = repoManager;
    this.schemaCreator = schemaCreator;
    this.versionManager = versionManager;
    this.args = args;
    this.schemaVersions = schemaVersions;
  }

  public void update(UpdateUI ui) throws OrmException {
    ensureSchemaCreated();

    int currentVersion = versionManager.read();
    if (currentVersion == 0) {
      // The only valid case where there is no refs/meta/version is when running 3.x init for the
      // first time on a site that previously ran init on 2.16. A freshly created 3.x site will have
      // seeded refs/meta/version during AllProjectsCreator, so it won't hit this block.
      checkNoteDbConfigFor216();
    }

    for (int nextVersion : requiredUpgrades(currentVersion, schemaVersions.keySet())) {
      try {
        ui.message(String.format("Migrating data to schema %d ...", nextVersion));
        NoteDbSchemaVersions.get(schemaVersions, nextVersion).upgrade(args, ui);
        versionManager.increment(nextVersion - 1);
      } catch (Exception e) {
        throw new OrmException(
            String.format("Failed to upgrade to schema version %d", nextVersion), e);
      }
    }
  }

  private void ensureSchemaCreated() throws OrmException {
    try {
      schemaCreator.ensureCreated();
    } catch (IOException | ConfigInvalidException e) {
      throw new OrmException("Cannot initialize Gerrit site");
    }
  }

  // Config#getEnum requires this to be public, so give it an off-putting name.
  public enum PrimaryStorageFor216Compatibility {
    REVIEW_DB,
    NOTE_DB
  }

  private void checkNoteDbConfigFor216() throws OrmException {
    // Check that the NoteDb migration config matches what we expect from a site that both:
    // * Completed the change migration to NoteDB.
    // * Ran schema upgrades from a 2.16 final release.

    if (!cfg.getBoolean("noteDb", "changes", "write", false)
        || !cfg.getBoolean("noteDb", "changes", "read", false)
        || cfg.getEnum(
                "noteDb", "changes", "primaryStorage", PrimaryStorageFor216Compatibility.REVIEW_DB)
            != PrimaryStorageFor216Compatibility.NOTE_DB
        || !cfg.getBoolean("noteDb", "changes", "disableReviewDb", false)) {
      throw new OrmException(
          "You appear to be upgrading from a 2.x site, but the NoteDb change migration was"
              + " not completed. See documentation:\n"
              + "https://gerrit-review.googlesource.com/Documentation/note-db.html#migration");
    }

    // We don't have a direct way to check that 2.16 init was run; the most obvious side effect
    // would be upgrading the *ReviewDb* schema to the latest 2.16 schema version. But in 3.x we can
    // no longer access ReviewDb, so we can't check that directly.
    //
    // Instead, check for a NoteDb-specific side effect of the migration process: the presence of
    // the NoteDb group sequence ref. This is created by the schema 163 migration, which was part of
    // 2.16 and not 2.15.
    //
    // There are a few corner cases where we will proceed even if the schema is not fully up to
    // date:
    //  * If a user happened to run init from master after schema 163 was added but before 2.16
    //    final. We assume that someone savvy enough to do that has followed the documented
    //    requirement of upgrading to 2.16 final before 3.0.
    //  * If a user ran init in 2.16.x and the upgrade to 163 succeeded but a later update failed.
    //    In this case the server literally will not start under 2.16. We assume the user will fix
    //    this and get 2.16 running rather than abandoning 2.16 and jumping to 3.0 at this point.
    try (Repository allUsers = repoManager.openRepository(allUsersName)) {
      if (allUsers.exactRef(RefNames.REFS_SEQUENCES + Sequences.NAME_GROUPS) == null) {
        throw new OrmException(
            "You appear to be upgrading to 3.x from a version prior to 2.16; you must upgrade to"
                + " 2.16.x first");
      }
    } catch (IOException e) {
      throw new OrmException("Failed to check NoteDb migration state", e);
    }
  }

  @VisibleForTesting
  static ImmutableList<Integer> requiredUpgrades(
      int currentVersion, ImmutableSortedSet<Integer> allVersions) throws OrmException {
    int firstVersion = allVersions.first();
    int latestVersion = allVersions.last();
    if (currentVersion == latestVersion) {
      return ImmutableList.of();
    } else if (currentVersion > latestVersion) {
      throw new OrmException(
          String.format(
              "Cannot downgrade NoteDb schema from version %d to %d",
              currentVersion, latestVersion));
    }

    int firstUpgradeVersion;
    if (currentVersion == 0) {
      // Bootstrap NoteDb version to minimum supported schema number.
      firstUpgradeVersion = firstVersion;
    } else {
      if (currentVersion < firstVersion - 1) {
        throw new OrmException(
            String.format(
                "Cannot skip NoteDb schema from version %d to %d", currentVersion, firstVersion));
      }
      firstUpgradeVersion = currentVersion + 1;
    }
    return IntStream.rangeClosed(firstUpgradeVersion, latestVersion)
        .boxed()
        .collect(toImmutableList());
  }
}
