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

import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.config.ConfigUtil;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.git.WorkQueue.Executor;
import com.google.gerrit.server.project.ProjectControl;
import com.google.gerrit.server.util.RequestScopePropagator;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.FactoryModuleBuilder;
import com.google.inject.Inject;

import com.google.inject.name.Named;
import com.google.inject.PrivateModule;
import com.google.inject.Provides;
import com.google.inject.Singleton;

import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.PreReceiveHook;
import org.eclipse.jgit.transport.ReceiveCommand;
import org.eclipse.jgit.transport.ReceiveCommand.Result;
import org.eclipse.jgit.transport.ReceivePack;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.OutputStream;
import java.util.Collection;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/** Hook that delegates to {@link ReceiveCommits} in a worker thread. */
public class AsyncReceiveCommits implements PreReceiveHook {
  private static final Logger log =
      LoggerFactory.getLogger(AsyncReceiveCommits.class);

  private static final String TIMEOUT_NAME = "ReceiveCommitsOverallTimeout";

  public interface Factory {
    AsyncReceiveCommits create(ProjectControl projectControl,
        Repository repository);
  }

  public static class Module extends PrivateModule {
    @Override
    public void configure() {
      install(new FactoryModuleBuilder()
          .build(AsyncReceiveCommits.Factory.class));
      expose(AsyncReceiveCommits.Factory.class);
      // Don't expose the binding for ReceiveCommits.Factory. All callers should
      // be using AsyncReceiveCommits.Factory instead.
      install(new FactoryModuleBuilder()
          .build(ReceiveCommits.Factory.class));
    }

    @Provides
    @Singleton
    @Named(TIMEOUT_NAME)
    long getTimeoutMillis(@GerritServerConfig final Config cfg) {
      return ConfigUtil.getTimeUnit(
          cfg, "receive", null, "timeout",
          TimeUnit.MINUTES.toMillis(2),
          TimeUnit.MILLISECONDS);
    }
  }

  private class Worker implements ProjectRunnable {
    private final Collection<ReceiveCommand> commands;

    private Worker(final Collection<ReceiveCommand> commands) {
      this.commands = commands;
    }

    @Override
    public void run() {
      rc.processCommands(commands, progress);
    }

    @Override
    public Project.NameKey getProjectNameKey() {
      return rc.getProject().getNameKey();
    }

    @Override
    public String getRemoteName() {
      return null;
    }

    @Override
    public boolean hasCustomizedPrint() {
      return true;
    }

    @Override
    public String toString() {
      return "receive-commits";
    }
  }

  private class MessageSenderOutputStream extends OutputStream {
    @Override
    public void write(int b) {
      rc.getMessageSender().sendBytes(new byte[]{(byte)b});
    }

    @Override
    public void write(byte[] what, int off, int len) {
      rc.getMessageSender().sendBytes(what, off, len);
    }

    @Override
    public void write(byte[] what) {
      rc.getMessageSender().sendBytes(what);
    }

    @Override
    public void flush() {
      rc.getMessageSender().flush();
    }
  }

  private final ReceiveCommits rc;
  private final Executor executor;
  private final RequestScopePropagator scopePropagator;
  private final MultiProgressMonitor progress;
  private final long timeoutMillis;

  @Inject
  AsyncReceiveCommits(final ReceiveCommits.Factory factory,
      @ReceiveCommitsExecutor final Executor executor,
      final RequestScopePropagator scopePropagator,
      @Named(TIMEOUT_NAME) final long timeoutMillis,
      @Assisted final ProjectControl projectControl,
      @Assisted final Repository repo) {
    this.executor = executor;
    this.scopePropagator = scopePropagator;
    rc = factory.create(projectControl, repo);
    rc.getReceivePack().setPreReceiveHook(this);

    progress = new MultiProgressMonitor(
        new MessageSenderOutputStream(), "Processing changes");
    this.timeoutMillis = timeoutMillis;
  }

  @Override
  public void onPreReceive(final ReceivePack rp,
      final Collection<ReceiveCommand> commands) {
    try {
      progress.waitFor(
          executor.submit(scopePropagator.wrap(new Worker(commands))),
          timeoutMillis, TimeUnit.MILLISECONDS);
    } catch (ExecutionException e) {
      log.warn("Error in ReceiveCommits", e);
      rc.addError("internal error while processing changes " + e.getMessage());
      // ReceiveCommits has tried its best to catch errors, so anything at this
      // point is very bad.
      for (final ReceiveCommand c : commands) {
        if (c.getResult() == Result.NOT_ATTEMPTED) {
          c.setResult(Result.REJECTED_OTHER_REASON, "internal error");
        }
      }
    } finally {
      rc.sendMessages();
    }
  }

  public ReceiveCommits getReceiveCommits() {
    return rc;
  }
}
