// Copyright (C) 2013 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.restapi.project;

import static com.google.common.base.Preconditions.checkState;
import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.gerrit.common.data.GarbageCollectionResult;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.extensions.annotations.RequiresCapability;
import com.google.gerrit.extensions.registration.DynamicItem;
import com.google.gerrit.extensions.restapi.BinaryResult;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.webui.UiAction;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.config.UrlFormatter;
import com.google.gerrit.server.git.GarbageCollection;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.WorkQueue;
import com.google.gerrit.server.ioutil.HexFormat;
import com.google.gerrit.server.project.ProjectResource;
import com.google.gerrit.server.restapi.project.GarbageCollect.Input;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.Optional;

@RequiresCapability(GlobalCapability.RUN_GC)
@Singleton
public class GarbageCollect
    implements RestModifyView<ProjectResource, Input>, UiAction<ProjectResource> {
  public static class Input {
    public boolean showProgress;
    public boolean aggressive;
    public boolean async;
  }

  private final boolean canGC;
  private final GarbageCollection.Factory garbageCollectionFactory;
  private final WorkQueue workQueue;
  private final DynamicItem<UrlFormatter> urlFormatter;

  @Inject
  GarbageCollect(
      GitRepositoryManager repoManager,
      GarbageCollection.Factory garbageCollectionFactory,
      WorkQueue workQueue,
      DynamicItem<UrlFormatter> urlFormatter) {
    this.workQueue = workQueue;
    this.urlFormatter = urlFormatter;
    this.canGC = repoManager.canPerformGC();
    this.garbageCollectionFactory = garbageCollectionFactory;
  }

  @Override
  public Object apply(ProjectResource rsrc, Input input) {
    Project.NameKey project = rsrc.getNameKey();
    if (input.async) {
      return applyAsync(project, input);
    }
    return applySync(project, input);
  }

  private Response.Accepted applyAsync(Project.NameKey project, Input input) {
    Runnable job =
        new Runnable() {
          @Override
          public void run() {
            runGC(project, input, null);
          }

          @Override
          public String toString() {
            return "Run "
                + (input.aggressive ? "aggressive " : "")
                + "garbage collection on project "
                + project.get();
          }
        };

    @SuppressWarnings("unchecked")
    WorkQueue.Task<Void> task = (WorkQueue.Task<Void>) workQueue.getDefaultQueue().submit(job);

    Optional<String> url =
        urlFormatter
            .get()
            .getRestUrl("a/config/server/tasks/" + HexFormat.fromInt(task.getTaskId()));
    // We're in a HTTP handler, so must be present.
    checkState(url.isPresent());
    return Response.accepted(url.get());
  }

  @SuppressWarnings("resource")
  private BinaryResult applySync(Project.NameKey project, Input input) {
    return new BinaryResult() {
      @Override
      public void writeTo(OutputStream out) throws IOException {
        PrintWriter writer =
            new PrintWriter(new OutputStreamWriter(out, UTF_8)) {
              @Override
              public void println() {
                write('\n');
              }
            };
        try {
          PrintWriter progressWriter = input.showProgress ? writer : null;
          GarbageCollectionResult result = runGC(project, input, progressWriter);
          String msg = "Garbage collection completed successfully.";
          if (result.hasErrors()) {
            for (GarbageCollectionResult.Error e : result.getErrors()) {
              switch (e.getType()) {
                case REPOSITORY_NOT_FOUND:
                  msg = "Error: project \"" + e.getProjectName() + "\" not found.";
                  break;
                case GC_ALREADY_SCHEDULED:
                  msg =
                      "Error: garbage collection for project \""
                          + e.getProjectName()
                          + "\" was already scheduled.";
                  break;
                case GC_FAILED:
                  msg =
                      "Error: garbage collection for project \""
                          + e.getProjectName()
                          + "\" failed.";
                  break;
                default:
                  msg =
                      "Error: garbage collection for project \""
                          + e.getProjectName()
                          + "\" failed: "
                          + e.getType()
                          + ".";
              }
            }
          }
          writer.println(msg);
        } finally {
          writer.flush();
        }
      }
    }.setContentType("text/plain").setCharacterEncoding(UTF_8).disableGzip();
  }

  GarbageCollectionResult runGC(Project.NameKey project, Input input, PrintWriter progressWriter) {
    return garbageCollectionFactory
        .create()
        .run(Collections.singletonList(project), input.aggressive, progressWriter);
  }

  @Override
  public UiAction.Description getDescription(ProjectResource rsrc) {
    return new UiAction.Description()
        .setLabel("Run GC")
        .setTitle("Triggers the Git Garbage Collection for this project.")
        .setVisible(canGC);
  }
}
