// Copyright (C) 2015 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.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.MultimapBuilder;
import com.google.common.collect.SetMultimap;
import com.google.common.collect.Sets;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Change.Status;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.Project.NameKey;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.GroupCollector;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefDatabase;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevSort;
import org.eclipse.jgit.revwalk.RevWalk;

public class Schema_108 extends SchemaVersion {
  private final GitRepositoryManager repoManager;

  @Inject
  Schema_108(Provider<Schema_107> prior, GitRepositoryManager repoManager) {
    super(prior);
    this.repoManager = repoManager;
  }

  @Override
  protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException {
    ui.message("Listing all changes ...");
    SetMultimap<Project.NameKey, Change.Id> openByProject = getOpenChangesByProject(db, ui);
    ui.message("done");

    ui.message("Updating groups for open changes ...");
    int i = 0;
    for (Map.Entry<Project.NameKey, Collection<Change.Id>> e : openByProject.asMap().entrySet()) {
      try (Repository repo = repoManager.openRepository(e.getKey());
          RevWalk rw = new RevWalk(repo)) {
        updateProjectGroups(db, repo, rw, (Set<Change.Id>) e.getValue(), ui);
      } catch (IOException | NoSuchChangeException err) {
        throw new OrmException(err);
      }
      if (++i % 100 == 0) {
        ui.message("  done " + i + " projects ...");
      }
    }
    ui.message("done");
  }

  private void updateProjectGroups(
      ReviewDb db, Repository repo, RevWalk rw, Set<Change.Id> changes, UpdateUI ui)
      throws OrmException, IOException {
    // Match sorting in ReceiveCommits.
    rw.reset();
    rw.sort(RevSort.TOPO);
    rw.sort(RevSort.REVERSE, true);

    RefDatabase refdb = repo.getRefDatabase();
    for (Ref ref : refdb.getRefs(Constants.R_HEADS).values()) {
      RevCommit c = maybeParseCommit(rw, ref.getObjectId(), ui);
      if (c != null) {
        rw.markUninteresting(c);
      }
    }

    ListMultimap<ObjectId, Ref> changeRefsBySha =
        MultimapBuilder.hashKeys().arrayListValues().build();
    ListMultimap<ObjectId, PatchSet.Id> patchSetsBySha =
        MultimapBuilder.hashKeys().arrayListValues().build();
    for (Ref ref : refdb.getRefs(RefNames.REFS_CHANGES).values()) {
      ObjectId id = ref.getObjectId();
      if (ref.getObjectId() == null) {
        continue;
      }
      id = id.copy();
      changeRefsBySha.put(id, ref);
      PatchSet.Id psId = PatchSet.Id.fromRef(ref.getName());
      if (psId != null && changes.contains(psId.getParentKey())) {
        patchSetsBySha.put(id, psId);
        RevCommit c = maybeParseCommit(rw, id, ui);
        if (c != null) {
          rw.markStart(c);
        }
      }
    }

    GroupCollector collector = GroupCollector.createForSchemaUpgradeOnly(changeRefsBySha, db);
    RevCommit c;
    while ((c = rw.next()) != null) {
      collector.visit(c);
    }

    updateGroups(db, collector, patchSetsBySha);
  }

  private static void updateGroups(
      ReviewDb db, GroupCollector collector, ListMultimap<ObjectId, PatchSet.Id> patchSetsBySha)
      throws OrmException {
    Map<PatchSet.Id, PatchSet> patchSets =
        db.patchSets().toMap(db.patchSets().get(patchSetsBySha.values()));
    for (Map.Entry<ObjectId, Collection<String>> e : collector.getGroups().asMap().entrySet()) {
      for (PatchSet.Id psId : patchSetsBySha.get(e.getKey())) {
        PatchSet ps = patchSets.get(psId);
        if (ps != null) {
          ps.setGroups(ImmutableList.copyOf(e.getValue()));
        }
      }
    }

    db.patchSets().update(patchSets.values());
  }

  private SetMultimap<Project.NameKey, Change.Id> getOpenChangesByProject(ReviewDb db, UpdateUI ui)
      throws OrmException {
    SortedSet<NameKey> projects = repoManager.list();
    SortedSet<NameKey> nonExistentProjects = Sets.newTreeSet();
    SetMultimap<Project.NameKey, Change.Id> openByProject =
        MultimapBuilder.hashKeys().hashSetValues().build();
    for (Change c : db.changes().all()) {
      Status status = c.getStatus();
      if (status != null && status.isClosed()) {
        continue;
      }

      NameKey projectKey = c.getProject();
      if (!projects.contains(projectKey)) {
        nonExistentProjects.add(projectKey);
      } else {
        // The old "submitted" state is not supported anymore
        // (thus status is null) but it was an opened state and needs
        // to be migrated as such
        openByProject.put(projectKey, c.getId());
      }
    }

    if (!nonExistentProjects.isEmpty()) {
      ui.message("Detected open changes referring to the following non-existent projects:");
      ui.message(Joiner.on(", ").join(nonExistentProjects));
      ui.message(
          "It is highly recommended to remove\n"
              + "the obsolete open changes, comments and patch-sets from your DB.\n");
    }
    return openByProject;
  }

  private static RevCommit maybeParseCommit(RevWalk rw, ObjectId id, UpdateUI ui)
      throws IOException {
    if (id != null) {
      try {
        RevObject obj = rw.parseAny(id);
        return (obj instanceof RevCommit) ? (RevCommit) obj : null;
      } catch (MissingObjectException moe) {
        ui.message("Missing object: " + id.getName() + "\n");
      }
    }
    return null;
  }
}
