// Copyright (C) 2014 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.pgm;

import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.gerrit.server.schema.DataSourceProvider.Context.MULTI_USER;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;

import com.google.common.collect.ImmutableList;
import com.google.gerrit.extensions.config.FactoryModule;
import com.google.gerrit.lifecycle.LifecycleManager;
import com.google.gerrit.pgm.util.BatchProgramModule;
import com.google.gerrit.pgm.util.RuntimeShutdown;
import com.google.gerrit.pgm.util.SiteProgram;
import com.google.gerrit.pgm.util.ThreadLimiter;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.git.GarbageCollection;
import com.google.gerrit.server.index.DummyIndexModule;
import com.google.gerrit.server.index.change.ChangeSchemaDefinitions;
import com.google.gerrit.server.notedb.rebuild.GcAllUsers;
import com.google.gerrit.server.notedb.rebuild.NoteDbMigrator;
import com.google.gerrit.server.plugins.PluginGuiceEnvironment;
import com.google.gerrit.server.schema.DataSourceType;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Provider;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import org.kohsuke.args4j.Option;
import org.kohsuke.args4j.spi.ExplicitBooleanOptionHandler;

public class MigrateToNoteDb extends SiteProgram {
  static final String TRIAL_USAGE =
      "Trial mode: migrate changes and turn on reading from NoteDb, but leave ReviewDb as the"
          + " source of truth";

  private static final int ISSUE_8022_THREAD_LIMIT = 4;

  @Option(name = "--threads", usage = "Number of threads to use for rebuilding NoteDb")
  private Integer threads;

  @Option(
      name = "--project",
      usage =
          "Only rebuild these projects, do no other migration; incompatible with --change;"
              + " recommended for debugging only")
  private List<String> projects = new ArrayList<>();

  @Option(
      name = "--change",
      usage =
          "Only rebuild these changes, do no other migration; incompatible with --project;"
              + " recommended for debugging only")
  private List<Integer> changes = new ArrayList<>();

  @Option(
      name = "--force",
      usage =
          "Force rebuilding changes where ReviewDb is still the source of truth, even if they"
              + " were previously migrated")
  private boolean force;

  @Option(name = "--trial", usage = TRIAL_USAGE)
  private boolean trial;

  @Option(
      name = "--sequence-gap",
      usage =
          "gap in change sequence numbers between last ReviewDb number and first NoteDb number;"
              + " negative indicates using the value of noteDb.changes.initialSequenceGap (default"
              + " 1000)")
  private int sequenceGap;

  @Option(
      name = "--reindex",
      usage =
          "Reindex all changes after migration; defaults to false in trial mode, true otherwise",
      handler = ExplicitBooleanOptionHandler.class)
  private Boolean reindex;

  private Injector dbInjector;
  private Injector sysInjector;
  private LifecycleManager dbManager;
  private LifecycleManager sysManager;

  @Inject private GcAllUsers gcAllUsers;
  @Inject private Provider<NoteDbMigrator.Builder> migratorBuilderProvider;

  @Override
  public int run() throws Exception {
    RuntimeShutdown.add(this::stop);
    try {
      mustHaveValidSite();
      dbInjector = createDbInjector(MULTI_USER);

      dbManager = new LifecycleManager();
      dbManager.add(dbInjector);
      dbManager.start();

      threads = limitThreads();

      sysInjector = createSysInjector();
      sysInjector.injectMembers(this);
      sysManager = new LifecycleManager();
      sysManager.add(sysInjector);
      sysInjector
          .getInstance(PluginGuiceEnvironment.class)
          .setDbCfgInjector(dbInjector, dbInjector);
      sysManager.start();

      try (NoteDbMigrator migrator =
          migratorBuilderProvider
              .get()
              .setThreads(threads)
              .setProgressOut(System.err)
              .setProjects(projects.stream().map(Project.NameKey::new).collect(toList()))
              .setChanges(changes.stream().map(Change.Id::new).collect(toList()))
              .setTrialMode(trial)
              .setForceRebuild(force)
              .setSequenceGap(sequenceGap)
              .build()) {
        if (!projects.isEmpty() || !changes.isEmpty()) {
          migrator.rebuild();
        } else {
          migrator.migrate();
        }
      }
      try (PrintWriter w = new PrintWriter(System.out, true)) {
        gcAllUsers.run(w);
      }
    } finally {
      stop();
    }

    boolean reindex = firstNonNull(this.reindex, !trial);
    if (!reindex) {
      return 0;
    }
    // Reindex all indices, to save the user from having to run yet another program by hand while
    // their server is offline.
    List<String> reindexArgs =
        ImmutableList.of(
            "--site-path",
            getSitePath().toString(),
            "--threads",
            Integer.toString(threads),
            "--index",
            ChangeSchemaDefinitions.NAME);
    System.out.println("Migration complete, reindexing changes with:");
    System.out.println("  reindex " + reindexArgs.stream().collect(joining(" ")));
    Reindex reindexPgm = new Reindex();
    return reindexPgm.main(reindexArgs.stream().toArray(String[]::new));
  }

  private int limitThreads() {
    if (threads != null) {
      return threads;
    }
    int actualThreads;
    int procs = Runtime.getRuntime().availableProcessors();
    DataSourceType dsType = dbInjector.getInstance(DataSourceType.class);
    if (dsType.getDriver().equals("org.h2.Driver") && procs > ISSUE_8022_THREAD_LIMIT) {
      System.out.println(
          "Not using more than "
              + ISSUE_8022_THREAD_LIMIT
              + " threads due to http://crbug.com/gerrit/8022");
      System.out.println("Can be increased by passing --threads, but may cause errors");
      actualThreads = ISSUE_8022_THREAD_LIMIT;
    } else {
      actualThreads = procs;
    }
    actualThreads = ThreadLimiter.limitThreads(dbInjector, actualThreads);
    return actualThreads;
  }

  private Injector createSysInjector() {
    return dbInjector.createChildInjector(
        new FactoryModule() {
          @Override
          public void configure() {
            install(dbInjector.getInstance(BatchProgramModule.class));
            install(new DummyIndexModule());
            factory(ChangeResource.Factory.class);
            factory(GarbageCollection.Factory.class);
          }
        });
  }

  private void stop() {
    try {
      LifecycleManager m = sysManager;
      sysManager = null;
      if (m != null) {
        m.stop();
      }
    } finally {
      LifecycleManager m = dbManager;
      dbManager = null;
      if (m != null) {
        m.stop();
      }
    }
  }
}
