// Copyright (C) 2008 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 com.google.gerrit.client.reviewdb.Account;
import com.google.gerrit.client.reviewdb.AccountGroup;
import com.google.gerrit.client.reviewdb.AccountGroupMember;
import com.google.gerrit.client.reviewdb.ApprovalCategory;
import com.google.gerrit.client.reviewdb.Change;
import com.google.gerrit.client.reviewdb.ChangeApproval;
import com.google.gerrit.client.reviewdb.PatchSet;
import com.google.gerrit.client.reviewdb.Project;
import com.google.gerrit.client.reviewdb.ProjectRight;
import com.google.gerrit.client.reviewdb.ReviewDb;
import com.google.gerrit.client.reviewdb.SystemConfig;
import com.google.gerrit.client.rpc.Common;
import com.google.gerrit.git.InvalidRepositoryException;
import com.google.gerrit.git.PatchSetImporter;
import com.google.gerrit.git.WorkQueue;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.GerritServer;
import com.google.gwtjsonrpc.server.XsrfException;
import com.google.gwtorm.client.OrmException;
import com.google.gwtorm.jdbc.JdbcSchema;

import org.spearce.jgit.lib.Constants;
import org.spearce.jgit.lib.LockFile;
import org.spearce.jgit.lib.ObjectId;
import org.spearce.jgit.lib.ProgressMonitor;
import org.spearce.jgit.lib.Ref;
import org.spearce.jgit.lib.RefUpdate;
import org.spearce.jgit.lib.Repository;
import org.spearce.jgit.lib.TextProgressMonitor;
import org.spearce.jgit.revwalk.RevCommit;
import org.spearce.jgit.revwalk.RevWalk;

import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Imports data from Gerrit 1 into Gerrit 2.
 * <p>
 * The tool assumes that <code>gerrit1_import/import_gerrit1.sql</code> has
 * already been executed on this schema. All existing ProjectRight entities are
 * wiped from the database and generated from scratch.
 * <p>
 * The tool requires Gerrit 1 tables (<code>gerrit1.$table_name</code>) through
 * the same database connection as the ReviewDb schema is on.
 */
public class ImportGerrit1 {
  private static GerritServer gs;
  private static ReviewDb db;
  private static Connection sql;
  private static ApprovalCategory verifyCategory;
  private static ApprovalCategory approveCategory;
  private static ApprovalCategory submitCategory;

  public static void main(final String[] argv) throws OrmException,
      XsrfException, IOException, SQLException, InvalidRepositoryException {
    try {
      mainImpl(argv);
    } finally {
      WorkQueue.terminate();
    }
  }

  private static void mainImpl(final String[] argv) throws OrmException,
      XsrfException, IOException, SQLException, InvalidRepositoryException {
    final ProgressMonitor pm = new TextProgressMonitor();
    gs = GerritServer.getInstance();
    db = Common.getSchemaFactory().open();
    sql = ((JdbcSchema) db).getConnection();
    try {
      verifyCategory = db.approvalCategories().byName("Verified");
      approveCategory = db.approvalCategories().byName("Code Review");
      submitCategory = db.approvalCategories().get(ApprovalCategory.SUBMIT);

      final Statement query = sql.createStatement();
      java.sql.ResultSet srcs;

      // Set project descriptions back into git
      //
      pm.start(1);
      pm.beginTask("Export project descriptions", ProgressMonitor.UNKNOWN);
      srcs = query.executeQuery("SELECT p.project_id FROM projects p");
      while (srcs.next()) {
        final Project.Id projectId = new Project.Id(srcs.getInt(1));
        if (ProjectRight.WILD_PROJECT.equals(projectId)) {
          continue;
        }
        final Project proj = db.projects().get(projectId);
        final Repository e;
        final LockFile f;

        e = gs.getRepositoryCache().get(proj.getName());
        f = new LockFile(new File(e.getDirectory(), "description"));
        if (f.lock()) {
          String d = proj.getDescription();
          if (d != null) {
            d = d.trim() + "\n";
          } else {
            d = "";
          }
          f.write(Constants.encode(d));
          f.commit();
        } else {
          throw new IOException("Cannot set description for " + proj.getName());
        }
        pm.update(1);
      }
      srcs.close();
      pm.endTask();

      // Convert the approval right data from projects.
      //
      pm.start(1);
      pm.beginTask("Import project rights", ProgressMonitor.UNKNOWN);
      query.executeUpdate("DELETE FROM project_rights");
      insertApprovalWildCard();
      insertAccessWildCard();
      srcs =
          query.executeQuery("SELECT p.project_id, r.ar_key"
              + " FROM gerrit1.project_code_reviews r, projects p"
              + " WHERE p.project_id = r.project_id");
      while (srcs.next()) {
        final Project.Id projectId = new Project.Id(srcs.getInt(1));
        final String arKey = srcs.getString(2);
        doImport(projectId, arKey);
        pm.update(1);
      }
      srcs.close();
      pm.endTask();

      // Compute the sort keys for change entities
      //
      srcs = query.executeQuery("SELECT change_id FROM changes");
      final ArrayList<Change.Id> changesToDo = new ArrayList<Change.Id>();
      while (srcs.next()) {
        final Change.Id changeId = new Change.Id(srcs.getInt(1));
        changesToDo.add(changeId);
      }
      srcs.close();
      pm.start(1);
      pm.beginTask("Compute sort keys", changesToDo.size());
      for (final Change.Id changeId : changesToDo) {
        final Change c = db.changes().get(changeId);
        ChangeUtil.computeSortKey(c);
        final List<ChangeApproval> approvals =
            db.changeApprovals().byChange(changeId).toList();
        for (final ChangeApproval a : approvals) {
          a.cache(c);
        }
        db.changeApprovals().update(approvals);
        db.changes().update(Collections.singleton(c));
        pm.update(1);
      }
      pm.endTask();

      // Rebuild the cached PatchSet information directly from Git.
      // There's some oddities in the Gerrit 1 data that we got from
      // Google App Engine's data store; the quickest way to fix it
      // is to just recache the data from Git.
      //
      srcs =
          query.executeQuery("SELECT change_id,patch_set_id FROM patch_sets");
      final ArrayList<PatchSet.Id> psToDo = new ArrayList<PatchSet.Id>();
      while (srcs.next()) {
        final Change.Id changeId = new Change.Id(srcs.getInt(1));
        final PatchSet.Id psId = new PatchSet.Id(changeId, srcs.getInt(2));
        psToDo.add(psId);
      }
      query.close();

      final Map<String, Set<String>> validRefs =
          new HashMap<String, Set<String>>();
      pm.start(1);
      pm.beginTask("Import patch sets", psToDo.size());
      for (final PatchSet.Id psId : psToDo) {
        final Change c = db.changes().get(psId.getParentKey());
        final PatchSet ps = db.patchSets().get(psId);
        final String projectName = c.getDest().getParentKey().get();
        final Repository repo = gs.getRepositoryCache().get(projectName);
        final RevWalk rw = new RevWalk(repo);
        final RevCommit src =
            rw.parseCommit(ObjectId.fromString(ps.getRevision().get()));
        new PatchSetImporter(db, repo, src, ps, false).run();
        Set<String> s = validRefs.get(projectName);
        if (s == null) {
          s = new HashSet<String>();
          validRefs.put(projectName, s);
        }
        s.add(ps.getRefName());
        pm.update(1);
      }
      pm.endTask();

      pruneProjectRefs(pm, validRefs);
    } finally {
      db.close();
    }
  }

  private static void pruneProjectRefs(final ProgressMonitor pm,
      final Map<String, Set<String>> validRefs) throws OrmException,
      IOException {
    final List<Project> pToClean = db.projects().all().toList();
    pm.start(1);
    pm.beginTask("Prune old refs", pToClean.size());
    for (final Project p : pToClean) {
      final Repository repo;
      try {
        repo = gs.getRepositoryCache().get(p.getName());
      } catch (InvalidRepositoryException e) {
        pm.update(1);
        continue;
      }

      Set<String> valid = validRefs.get(p.getName());
      if (valid == null) {
        valid = Collections.emptySet();
      }

      final RevWalk rw = new RevWalk(repo);
      for (final Ref r : repo.getAllRefs().values()) {
        boolean delete = false;
        if (r.getName().startsWith("refs/merges/")) {
          delete = true;
        }
        if (r.getName().startsWith("refs/changes/")
            && !valid.contains(r.getName())) {
          delete = true;
        }
        if (delete) {
          final RefUpdate u = repo.updateRef(r.getName());
          u.setForceUpdate(true);
          u.delete(rw);
        }
      }
      pm.update(1);
    }
    pm.endTask();
  }

  private static void insertApprovalWildCard() throws OrmException {
    final ProjectRight.Key key =
        new ProjectRight.Key(ProjectRight.WILD_PROJECT,
            approveCategory.getId(), db.systemConfig().get(
                new SystemConfig.Key()).registeredGroupId);
    final ProjectRight pr = new ProjectRight(key);
    pr.setMinValue((short) -1);
    pr.setMaxValue((short) 1);
    db.projectRights().insert(Collections.singleton(pr));
  }

  private static void insertAccessWildCard() throws OrmException {
    final ProjectRight.Key key =
        new ProjectRight.Key(ProjectRight.WILD_PROJECT, ApprovalCategory.READ,
            db.systemConfig().get(new SystemConfig.Key()).anonymousGroupId);
    final ProjectRight pr = new ProjectRight(key);
    pr.setMinValue((short) 1);
    pr.setMaxValue((short) 1);
    db.projectRights().insert(Collections.singleton(pr));
  }

  private static void doImport(final Project.Id projectId, final String arKey)
      throws OrmException, SQLException {
    final int arId = findId(arKey);
    if (arId < 0) {
      return;
    }

    final Project proj = db.projects().get(projectId);
    final Set<AccountGroup.Id> approverg = groups(arId, "approver");
    final Set<AccountGroup.Id> verifierg = groups(arId, "verifier");
    final Set<AccountGroup.Id> submitterg = groups(arId, "submitter");

    final Set<Account.Id> approveru = users(arId, "approver");
    final Set<Account.Id> verifieru = users(arId, "verifier");
    final Set<Account.Id> submitteru = users(arId, "submitter");

    importCat(proj, "approvers", approveCategory, approverg, approveru);
    importCat(proj, "verifiers", verifyCategory, verifierg, verifieru);
    importCat(proj, "submitters", submitCategory, submitterg, submitteru);
  }

  private static void importCat(final Project proj, final String type,
      final ApprovalCategory category, final Set<AccountGroup.Id> groups,
      final Set<Account.Id> users) throws OrmException {
    final HashSet<Account.Id> needGroup = new HashSet<Account.Id>(users);
    for (final AccountGroup.Id groupId : groups) {
      insertRight(proj, category, groupId);
      for (final Iterator<Account.Id> i = needGroup.iterator(); i.hasNext();) {
        if (Common.getGroupCache().isInGroup(i.next(), groupId)) {
          i.remove();
        }
      }
    }

    if (!needGroup.isEmpty()) {
      final AccountGroup.Id groupId =
          new AccountGroup.Id(db.nextAccountGroupId());
      final AccountGroup group =
          new AccountGroup(new AccountGroup.NameKey(shortName(proj) + "_"
              + proj.getId().get() + "-" + type), groupId);
      group.setOwnerGroupId(proj.getOwnerGroupId());
      group.setDescription(proj.getName() + " " + type);
      db.accountGroups().insert(Collections.singleton(group));
      for (final Account.Id aId : needGroup) {
        db.accountGroupMembers().insert(
            Collections.singleton(new AccountGroupMember(
                new AccountGroupMember.Key(aId, groupId))));
      }
      insertRight(proj, category, groupId);
    }
  }

  private static void insertRight(final Project proj,
      final ApprovalCategory category, final AccountGroup.Id groupId)
      throws OrmException {
    final ProjectRight.Key key =
        new ProjectRight.Key(proj.getId(), category.getId(), groupId);
    final ProjectRight pr = new ProjectRight(key);
    if (category == approveCategory) {
      pr.setMinValue((short) -2);
      pr.setMaxValue((short) 2);
    } else if (category == verifyCategory) {
      pr.setMinValue((short) -1);
      pr.setMaxValue((short) 1);
    } else if (category == submitCategory) {
      pr.setMinValue((short) 1);
      pr.setMaxValue((short) 1);
    } else {
      throw new OrmException("Cannot import category " + category.getId());
    }
    db.projectRights().insert(Collections.singleton(pr));
  }

  private static String shortName(final Project proj) {
    final String n = proj.getName();
    final int s = n.lastIndexOf('/');
    return 0 < s ? n.substring(s + 1) : n;
  }

  private static Set<AccountGroup.Id> groups(final int arId, final String type)
      throws SQLException {
    final PreparedStatement ps =
        sql.prepareStatement("SELECT g.group_id FROM account_groups g,"
            + " gerrit1.approval_right_groups s, gerrit1.account_groups o"
            + " WHERE s.ar_id = ? AND s.type = ?"
            + " AND o.gae_key = s.group_key AND (g.name = o.name"
            + " OR (g.name = 'Administrators' AND o.name = 'admin'))");
    try {
      ps.setInt(1, arId);
      ps.setString(2, type);
      final java.sql.ResultSet rs = ps.executeQuery();
      try {
        final HashSet<AccountGroup.Id> r = new HashSet<AccountGroup.Id>();
        while (rs.next()) {
          r.add(new AccountGroup.Id(rs.getInt(1)));
        }
        return r;
      } finally {
        rs.close();
      }
    } finally {
      ps.close();
    }
  }

  private static Set<Account.Id> users(final int arId, final String type)
      throws SQLException {
    final PreparedStatement ps =
        sql.prepareStatement("SELECT a.account_id FROM accounts a,"
            + " gerrit1.approval_right_users s"
            + " WHERE s.ar_id = ? AND s.type = ?"
            + " AND a.preferred_email = s.email");
    try {
      ps.setInt(1, arId);
      ps.setString(2, type);
      final java.sql.ResultSet rs = ps.executeQuery();
      try {
        final HashSet<Account.Id> r = new HashSet<Account.Id>();
        while (rs.next()) {
          r.add(new Account.Id(rs.getInt(1)));
        }
        return r;
      } finally {
        rs.close();
      }
    } finally {
      ps.close();
    }
  }

  private static int findId(final String arKey) throws SQLException {
    final PreparedStatement ps =
        sql.prepareStatement("SELECT ar_id FROM gerrit1.approval_rights"
            + " WHERE gae_key=?");
    try {
      ps.setString(1, arKey);
      final java.sql.ResultSet rs = ps.executeQuery();
      try {
        if (rs.next()) {
          return rs.getInt(1);
        }
        return -1;
      } finally {
        rs.close();
      }
    } finally {
      ps.close();
    }
  }
}
