// 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.git;

import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.project.ProjectCache;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;

import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.PersonIdent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class RenameGroupOp extends DefaultQueueOp {
  public interface Factory {
    RenameGroupOp create(@Assisted("author") PersonIdent author,
        @Assisted AccountGroup.UUID uuid, @Assisted("oldName") String oldName,
        @Assisted("newName") String newName);
  }

  private static final int MAX_TRIES = 10;
  private static final Logger log =
      LoggerFactory.getLogger(RenameGroupOp.class);

  private final ProjectCache projectCache;
  private final MetaDataUpdate.Server metaDataUpdateFactory;

  private final PersonIdent author;
  private final AccountGroup.UUID uuid;
  private final String oldName;
  private final String newName;
  private final List<Project.NameKey> retryOn;

  private boolean tryingAgain;

  @Inject
  public RenameGroupOp(WorkQueue workQueue, ProjectCache projectCache,
      MetaDataUpdate.Server metaDataUpdateFactory,

      @Assisted("author") PersonIdent author, @Assisted AccountGroup.UUID uuid,
      @Assisted("oldName") String oldName, @Assisted("newName") String newName) {
    super(workQueue);
    this.projectCache = projectCache;
    this.metaDataUpdateFactory = metaDataUpdateFactory;

    this.author = author;
    this.uuid = uuid;
    this.oldName = oldName;
    this.newName = newName;
    this.retryOn = new ArrayList<>();
  }

  @Override
  public void run() {
    Iterable<Project.NameKey> names = tryingAgain
        ? retryOn
        : projectCache.all();
    for (Project.NameKey projectName : names) {
      ProjectConfig config = projectCache.get(projectName).getConfig();
      GroupReference ref = config.getGroup(uuid);
      if (ref == null || newName.equals(ref.getName())) {
        continue;
      }

      try {
        MetaDataUpdate md = metaDataUpdateFactory.create(projectName);
        try {
          rename(md);
        } finally {
          md.close();
        }
      } catch (RepositoryNotFoundException noProject) {
        continue;
      } catch (ConfigInvalidException | IOException err) {
        log.error("Cannot rename group " + oldName + " in " + projectName, err);
      }
    }

    // If one or more projects did not update, wait 5 minutes
    // and give it another attempt.
    if (!retryOn.isEmpty() && !tryingAgain) {
      tryingAgain = true;
      start(5, TimeUnit.MINUTES);
    }
  }

  private void rename(MetaDataUpdate md) throws IOException,
      ConfigInvalidException {
    boolean success = false;
    for (int attempts = 0; !success && attempts < MAX_TRIES; attempts++) {
      ProjectConfig config = ProjectConfig.read(md);

      // The group isn't referenced, or its name has been fixed already.
      //
      GroupReference ref = config.getGroup(uuid);
      if (ref == null || newName.equals(ref.getName())) {
        projectCache.evict(config.getProject());
        return;
      }

      ref.setName(newName);
      md.getCommitBuilder().setAuthor(author);
      md.setMessage("Rename group " + oldName + " to " + newName + "\n");
      try {
        config.commit(md);
        projectCache.evict(config.getProject());
        success = true;
      } catch (IOException e) {
        log.error("Could not commit rename of group " + oldName + " to "
            + newName + " in " + md.getProjectName().get(), e);
        try {
          Thread.sleep(25 /* milliseconds */);
        } catch (InterruptedException wakeUp) {
          continue;
        }
      }
    }

    if (!success) {
      if (tryingAgain) {
        log.warn("Could not rename group " + oldName + " to " + newName
            + " in " + md.getProjectName().get());
      } else {
        retryOn.add(md.getProjectName());
      }
    }
  }

  @Override
  public String toString() {
    return "Rename Group " + oldName;
  }
}
