// 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.git.LocalDiskRepositoryManager;
import com.google.gerrit.server.git.MetaDataUpdate;
import com.google.gerrit.server.git.NoReplication;
import com.google.gerrit.server.git.ProjectConfig;
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.util.Collections;

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

  @Inject
  Schema_57(Provider<Schema_56> prior, SitePaths site,
      LocalDiskRepositoryManager 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(new NoReplication(), 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");
        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()
            &&  db.accountGroupIncludes().byGroup(sc.batchUsersGroupId).toList().isEmpty()) {
          // 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");
        if (!config.commit(md)) {
          throw new OrmException("Cannot update " + allProjects);
        }
      } 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));
  }
}
