// Copyright (C) 2012 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.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.primitives.Longs;
import com.google.gerrit.common.data.AccessSection;
import com.google.gerrit.common.data.ContributorAgreement;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.common.data.PermissionRule;
import com.google.gerrit.common.data.PermissionRule.Action;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.AccountGroupMember;
import com.google.gerrit.reviewdb.client.AccountGroupMemberAudit;
import com.google.gerrit.reviewdb.client.AccountGroupName;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.account.GroupUUID;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.config.AnonymousCowardName;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.MetaDataUpdate;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.git.VersionedMetaData.BatchMetaDataUpdate;
import com.google.gwtorm.jdbc.JdbcSchema;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;

import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.util.SystemReader;

import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;

public class Schema_65 extends SchemaVersion {
  private final AllProjectsName allProjects;
  private final GitRepositoryManager mgr;
  private final PersonIdent serverUser;
  private final @AnonymousCowardName String anonymousCowardName;

  @Inject
  Schema_65(Provider<Schema_64> prior,
      AllProjectsName allProjects,
      GitRepositoryManager mgr,
      @GerritPersonIdent PersonIdent serverUser,
      @AnonymousCowardName String anonymousCowardName) {
    super(prior);
    this.allProjects = allProjects;
    this.mgr = mgr;
    this.serverUser = serverUser;
    this.anonymousCowardName = anonymousCowardName;
  }

  @Override
  protected void migrateData(ReviewDb db, UpdateUI ui)
      throws OrmException, SQLException {
    Repository git;
    try {
      git = mgr.openRepository(allProjects);
    } catch (IOException e) {
      throw new OrmException(e);
    }
    try {
      MetaDataUpdate md =
          new MetaDataUpdate(GitReferenceUpdated.DISABLED, allProjects, git);
      ProjectConfig config = ProjectConfig.read(md);
      Map<Integer, ContributorAgreement> agreements = getAgreementToAdd(db, config);
      if (agreements.isEmpty()) {
        return;
      }
      ui.message("Moved contributor agreements to project.config");

      // Create the auto verify groups.
      List<AccountGroup.UUID> adminGroupUUIDs = getAdministrateServerGroups(db, config);
      for (ContributorAgreement agreement : agreements.values()) {
        if (agreement.getAutoVerify() != null) {
          getOrCreateGroupForIndividuals(db, config, adminGroupUUIDs, agreement);
        }
      }

      // Scan AccountAgreement
      long minTime = addAccountAgreements(db, config, adminGroupUUIDs, agreements);

      ProjectConfig base = ProjectConfig.read(md, null);
      for (ContributorAgreement agreement : agreements.values()) {
        base.replace(agreement);
      }
      base.getAccountsSection().setSameGroupVisibility(
          config.getAccountsSection().getSameGroupVisibility());

      BatchMetaDataUpdate batch = base.openUpdate(md);
      try {
        // Scan AccountGroupAgreement
        List<AccountGroupAgreement> groupAgreements =
            getAccountGroupAgreements(db, agreements);

        // Find the earliest change
        for (AccountGroupAgreement aga : groupAgreements) {
          minTime = Math.min(minTime, aga.getTime());
        }
        minTime -= 60 * 1000; // 1 Minute

        CommitBuilder commit = new CommitBuilder();
        commit.setAuthor(new PersonIdent(serverUser, new Date(minTime)));
        commit.setCommitter(new PersonIdent(serverUser, new Date(minTime)));
        commit.setMessage("Add the ContributorAgreements for upgrade to Gerrit Code Review schema 65\n");
        batch.write(commit);

        for (AccountGroupAgreement aga : groupAgreements) {
          AccountGroup group = db.accountGroups().get(aga.groupId);
          if (group == null) {
            continue;
          }

          ContributorAgreement agreement = agreements.get(aga.claId);
          agreement.getAccepted().add(new PermissionRule(config.resolve(group)));
          base.replace(agreement);

          PersonIdent ident = null;
          if (aga.reviewedBy != null) {
            Account ua = db.accounts().get(aga.reviewedBy);
            if (ua != null) {
              String name = ua.getFullName();
              String email = ua.getPreferredEmail();

              if (email == null || email.isEmpty()) {
                // No preferred email is configured. Use a generic identity so we
                // don't leak an address the user may have given us, but doesn't
                // necessarily want to publish through Git records.
                //
                String user = ua.getUserName();
                if (user == null || user.isEmpty()) {
                  user = "account-" + ua.getId().toString();
                }

                String host = SystemReader.getInstance().getHostname();
                email = user + "@" + host;
              }

              if (name == null || name.isEmpty()) {
                final int at = email.indexOf('@');
                if (0 < at) {
                  name = email.substring(0, at);
                } else {
                  name = anonymousCowardName;
                }
              }

              ident = new PersonIdent(name, email, new Date(aga.getTime()), TimeZone.getDefault());
            }
          }
          if (ident == null) {
            ident = new PersonIdent(serverUser, new Date(aga.getTime()));
          }

          // Build the commits such that it keeps track of the date added and
          // who added it.
          commit = new CommitBuilder();
          commit.setAuthor(ident);
          commit.setCommitter(new PersonIdent(serverUser, new Date(aga.getTime())));

          String msg = String.format("Accept %s contributor agreement for %s\n",
              agreement.getName(), group.getName());
          if (!Strings.isNullOrEmpty(aga.reviewComments)) {
            msg += "\n" + aga.reviewComments + "\n";
          }
          commit.setMessage(msg);
          batch.write(commit);
        }

        // Merge the agreements with the other data in project.config.
        commit = new CommitBuilder();
        commit.setAuthor(serverUser);
        commit.setCommitter(serverUser);
        commit.setMessage("Upgrade to Gerrit Code Review schema 65\n");
        commit.addParentId(config.getRevision());
        batch.write(config, commit);

        // Save the the final metadata.
        batch.commitAt(config.getRevision());
      } finally {
        batch.close();
      }
    } catch (IOException e) {
      throw new OrmException(e);
    } catch (ConfigInvalidException e) {
      throw new OrmException(e);
    } finally {
      git.close();
    }
  }

  private Map<Integer, ContributorAgreement> getAgreementToAdd(
      ReviewDb db, ProjectConfig config) throws SQLException {
    Statement stmt = ((JdbcSchema) db).getConnection().createStatement();
    try {
      ResultSet rs = stmt.executeQuery(
          "SELECT short_name, id, require_contact_information," +
          "       short_description, agreement_url, auto_verify " +
          "FROM contributor_agreements WHERE active = 'Y'");
      try {
        Map<Integer, ContributorAgreement> agreements = Maps.newHashMap();
        while (rs.next()) {
          String name = rs.getString(1);
          if (config.getContributorAgreement(name) != null) {
            continue; // already exists
          }
          ContributorAgreement a = config.getContributorAgreement(name, true);
          agreements.put(rs.getInt(2), a);

          a.setRequireContactInformation("Y".equals(rs.getString(3)));
          a.setDescription(rs.getString(4));
          a.setAgreementUrl(rs.getString(5));
          if ("Y".equals(rs.getString(6))) {
            a.setAutoVerify(new GroupReference(null, null));
          }
        }
        return agreements;
      } finally {
        rs.close();
      }
    } finally {
      stmt.close();
    }
  }

  private AccountGroup createGroup(ReviewDb db, String groupName,
      AccountGroup.UUID adminGroupUUID, String description)
          throws OrmException {
    final AccountGroup.Id groupId =
        new AccountGroup.Id(db.nextAccountGroupId());
    final AccountGroup.NameKey nameKey = new AccountGroup.NameKey(groupName);
    final AccountGroup.UUID uuid = GroupUUID.make(groupName, serverUser);
    final AccountGroup group = new AccountGroup(nameKey, groupId, uuid);
    group.setOwnerGroupUUID(adminGroupUUID);
    group.setDescription(description);
    final AccountGroupName gn = new AccountGroupName(group);
    // first insert the group name to validate that the group name hasn't
    // already been used to create another group
    db.accountGroupNames().insert(Collections.singleton(gn));
    db.accountGroups().insert(Collections.singleton(group));
    return group;
  }

  private List<AccountGroup.UUID> getAdministrateServerGroups(
      ReviewDb db, ProjectConfig cfg) {
    List<PermissionRule> rules = cfg.getAccessSection(AccessSection.GLOBAL_CAPABILITIES)
       .getPermission(GlobalCapability.ADMINISTRATE_SERVER)
       .getRules();

    List<AccountGroup.UUID> groups =
        Lists.newArrayListWithExpectedSize(rules.size());
    for (PermissionRule rule : rules) {
      if (rule.getAction() == Action.ALLOW) {
        groups.add(rule.getGroup().getUUID());
      }
    }
    if (groups.isEmpty()) {
      throw new IllegalStateException("no administrator group found");
    }

    return groups;
  }

  private GroupReference getOrCreateGroupForIndividuals(ReviewDb db,
      ProjectConfig config, List<AccountGroup.UUID> adminGroupUUIDs,
      ContributorAgreement agreement)
          throws OrmException {
    if (!agreement.getAccepted().isEmpty()) {
      return agreement.getAccepted().get(0).getGroup();
    }

    String name = "CLA Accepted - " + agreement.getName();
    AccountGroupName agn =
        db.accountGroupNames().get(new AccountGroup.NameKey(name));
    AccountGroup ag;
    if (agn != null) {
      ag = db.accountGroups().get(agn.getId());
      if (ag == null) {
        throw new IllegalStateException(
            "account group name exists but account group does not: " + name);
      }

      if (!adminGroupUUIDs.contains(ag.getOwnerGroupUUID())) {
        throw new IllegalStateException(
            "individual group exists with non admin owner group: " + name);
      }
    } else {
      ag = createGroup(db, name, adminGroupUUIDs.get(0),
          String.format("Users who have accepted the %s CLA", agreement.getName()));
    }
    GroupReference group = config.resolve(ag);
    agreement.setAccepted(Lists.newArrayList(new PermissionRule(group)));
    if (agreement.getAutoVerify() != null) {
      agreement.setAutoVerify(group);
    }

    // Don't allow accounts in the same individual CLA group to see each
    // other in same group visibility mode.
    List<PermissionRule> sameGroupVisibility =
        config.getAccountsSection().getSameGroupVisibility();
    PermissionRule rule = new PermissionRule(group);
    rule.setDeny();
    if (!sameGroupVisibility.contains(rule)) {
      sameGroupVisibility.add(rule);
    }
    return group;
  }

  private long addAccountAgreements(ReviewDb db, ProjectConfig config,
      List<AccountGroup.UUID> adminGroupUUIDs,
      Map<Integer, ContributorAgreement> agreements)
          throws SQLException, OrmException {
    Statement stmt = ((JdbcSchema) db).getConnection().createStatement();
    try {
      ResultSet rs = stmt.executeQuery(
          "SELECT account_id, cla_id, accepted_on, reviewed_by," +
          "       reviewed_on, review_comments " +
          "FROM account_agreements WHERE status = 'V'");
      try {
        long minTime = System.currentTimeMillis();
        while (rs.next()) {
          Account.Id accountId = new Account.Id(rs.getInt(1));
          Account.Id reviewerId = new Account.Id(rs.getInt(4));
          if (rs.wasNull()) {
            reviewerId = accountId;
          }

          int claId = rs.getInt(2);
          ContributorAgreement agreement = agreements.get(claId);
          if (agreement == null) {
            continue;  // Agreement is invalid
          }

          Timestamp acceptedOn = rs.getTimestamp(3);
          minTime = Math.min(minTime, acceptedOn.getTime());

          // Enter Agreement
          GroupReference individualGroup =
              getOrCreateGroupForIndividuals(db, config, adminGroupUUIDs, agreement);
          AccountGroup.Id groupId = db.accountGroups()
              .byUUID(individualGroup.getUUID())
              .toList()
              .get(0)
              .getId();

          final AccountGroupMember.Key key =
              new AccountGroupMember.Key(accountId, groupId);
          AccountGroupMember m = db.accountGroupMembers().get(key);
          if (m == null) {
            m = new AccountGroupMember(key);
            db.accountGroupMembersAudit().insert(
                Collections.singleton(
                    new AccountGroupMemberAudit(m, reviewerId, acceptedOn)));
            db.accountGroupMembers().insert(Collections.singleton(m));
          }
        }
        return minTime;
      } finally {
        rs.close();
      }
    } finally {
      stmt.close();
    }
  }

  private static class AccountGroupAgreement {
    private AccountGroup.Id groupId;
    private int claId;
    private Timestamp acceptedOn;
    private Account.Id reviewedBy;
    private Timestamp reviewedOn;
    private String reviewComments;

    private long getTime() {
      return (reviewedOn == null) ? acceptedOn.getTime() : reviewedOn.getTime();
    }
  }

  private List<AccountGroupAgreement> getAccountGroupAgreements(
      ReviewDb db, Map<Integer, ContributorAgreement> agreements)
          throws SQLException {

    Statement stmt = ((JdbcSchema) db).getConnection().createStatement();
    try {
      ResultSet rs = stmt.executeQuery(
          "SELECT group_id, cla_id, accepted_on, reviewed_by, reviewed_on, " +
          "       review_comments " +
          "FROM account_group_agreements");
      try {
        List<AccountGroupAgreement> groupAgreements = Lists.newArrayList();
        while (rs.next()) {
          AccountGroupAgreement a = new AccountGroupAgreement();
          a.groupId = new AccountGroup.Id(rs.getInt(1));
          a.claId = rs.getInt(2);
          if (!agreements.containsKey(a.claId)) {
            continue; // Agreement is invalid
          }
          a.acceptedOn = rs.getTimestamp(3);
          a.reviewedBy = new Account.Id(rs.getInt(4));
          if (rs.wasNull()) {
            a.reviewedBy = null;
          }

          a.reviewedOn = rs.getTimestamp(5);
          if (rs.wasNull()) {
            a.reviewedOn = null;
          }

          a.reviewComments = rs.getString(6);
          if (rs.wasNull()) {
            a.reviewComments = null;
          }
          groupAgreements.add(a);
        }
        Collections.sort(groupAgreements, new Comparator<AccountGroupAgreement>() {
          @Override
          public int compare(
              AccountGroupAgreement a1, AccountGroupAgreement a2) {
            return Longs.compare(a1.getTime(), a2.getTime());
          }
        });
        return groupAgreements;
      } finally {
        rs.close();
      }
    } finally {
      stmt.close();
    }
  }
}
