// Copyright (C) 2011 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.gerrit.common.data.AccessSection;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.common.data.PermissionRule;
import com.google.gerrit.common.data.PermissionRule.Action;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.AccountGroupName;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.SystemConfig;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.config.AllProjectsNameProvider;
import com.google.gerrit.server.config.SitePaths;
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.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.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS;

import java.io.IOException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collections;

public class Schema_57 extends SchemaVersion {
  private final SitePaths site;
  private final GitRepositoryManager mgr;
  private final PersonIdent serverUser;

  @Inject
  Schema_57(Provider<Schema_56> prior, SitePaths site,
      GitRepositoryManager mgr, @GerritPersonIdent PersonIdent serverUser) {
    super(prior);
    this.site = site;
    this.mgr = mgr;
    this.serverUser = serverUser;
  }

  @Override
  protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException {
    SystemConfig sc = db.systemConfig().get(new SystemConfig.Key());
    Project.NameKey allProjects = sc.wildProjectName;

    FileBasedConfig cfg = new FileBasedConfig(site.gerrit_config, FS.DETECTED);
    boolean cfgDirty = false;
    try {
      cfg.load();
    } catch (ConfigInvalidException err) {
      throw new OrmException("Cannot read " + site.gerrit_config, err);
    } catch (IOException err) {
      throw new OrmException("Cannot read " + site.gerrit_config, err);
    }

    if (!allProjects.get().equals(AllProjectsNameProvider.DEFAULT)) {
      ui.message("Setting gerrit.allProjects = " + allProjects.get());
      cfg.setString("gerrit", null, "allProjects", allProjects.get());
      cfgDirty = true;
    }

    try {
      Repository git = mgr.openRepository(allProjects);
      try {
        MetaDataUpdate md =
            new MetaDataUpdate(GitReferenceUpdated.DISABLED, allProjects, git);
        md.getCommitBuilder().setAuthor(serverUser);
        md.getCommitBuilder().setCommitter(serverUser);

        ProjectConfig config = ProjectConfig.read(md);
        AccessSection cap = config.getAccessSection(AccessSection.GLOBAL_CAPABILITIES, true);

        // Move the Administrators group reference to All-Projects.
        cap.getPermission(GlobalCapability.ADMINISTRATE_SERVER, true)
            .add(new PermissionRule(config.resolve(db.accountGroups().get(sc.adminGroupId))));

        // Move the repository.*.createGroup to Create Project.
        String[] createGroupList = cfg.getStringList("repository", "*", "createGroup");

        // Prepare the account_group_includes query
        PreparedStatement stmt = ((JdbcSchema) db).getConnection().
            prepareStatement("SELECT COUNT(1) FROM account_group_includes WHERE group_id = ?");
        boolean isAccountGroupEmpty = false;
        try {
          stmt.setInt(1, sc.batchUsersGroupId.get());
          ResultSet rs = stmt.executeQuery();
          if (rs.next()) {
            isAccountGroupEmpty = rs.getInt(1) == 0;
          }
        } finally {
          stmt.close();
        }

        for (String name : createGroupList) {
          AccountGroup.NameKey key = new AccountGroup.NameKey(name);
          AccountGroupName groupName = db.accountGroupNames().get(key);
          if (groupName == null) {
            continue;
          }

          AccountGroup group = db.accountGroups().get(groupName.getId());
          if (group == null) {
            continue;
          }

          cap.getPermission(GlobalCapability.CREATE_PROJECT, true)
              .add(new PermissionRule(config.resolve(group)));
        }
        if (createGroupList.length != 0) {
          ui.message("Moved repository.*.createGroup to 'Create Project' capability");
          cfg.unset("repository", "*", "createGroup");
          cfgDirty = true;
        }

        AccountGroup batch = db.accountGroups().get(sc.batchUsersGroupId);

        if (batch != null
            && db.accountGroupMembers().byGroup(sc.batchUsersGroupId).toList().isEmpty()
            && !isAccountGroupEmpty) {
          // If the batch user group is not used, delete it.
          //
          db.accountGroups().delete(Collections.singleton(batch));

          AccountGroupName name = db.accountGroupNames().get(batch.getNameKey());
          if (name != null) {
            db.accountGroupNames().delete(Collections.singleton(name));
          }
        } else if (batch != null) {
          cap.getPermission(GlobalCapability.PRIORITY, true)
              .getRule(config.resolve(batch), true)
              .setAction(Action.BATCH);
        }

        md.setMessage("Upgrade to Gerrit Code Review schema 57\n");
        config.commit(md);
      } catch (SQLException err) {
        throw new OrmException( "Cannot read account_group_includes", err);
      } finally {
        git.close();
      }
    } catch (ConfigInvalidException err) {
      throw new OrmException("Cannot read " + allProjects, err);
    } catch (IOException err) {
      throw new OrmException("Cannot update " + allProjects, err);
    }

    if (cfgDirty) {
      try {
        cfg.save();
      } catch (IOException err) {
        throw new OrmException("Cannot update " + site.gerrit_config, err);
      }
    }

    // We cannot set the columns to NULL, so use 0 and a DELETED tag.
    sc.adminGroupId = new AccountGroup.Id(0);
    sc.adminGroupUUID = new AccountGroup.UUID("DELETED");
    sc.anonymousGroupId = new AccountGroup.Id(0);
    sc.registeredGroupId = new AccountGroup.Id(0);
    sc.wildProjectName = new Project.NameKey("DELETED");
    sc.ownerGroupId = new AccountGroup.Id(0);
    sc.batchUsersGroupId = new AccountGroup.Id(0);
    sc.batchUsersGroupUUID = new AccountGroup.UUID("DELETED");
    sc.registerEmailPrivateKey = "DELETED";

    db.systemConfig().update(Collections.singleton(sc));
  }
}
