// Copyright (C) 2015 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.acceptance;

import com.google.common.collect.Lists;
import com.google.gerrit.acceptance.InProcessProtocol.Context;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.data.Capable;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.AccessPath;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.RemotePeer;
import com.google.gerrit.server.RequestCleanup;
import com.google.gerrit.server.config.GerritRequestModule;
import com.google.gerrit.server.config.RequestScopedReviewDbProvider;
import com.google.gerrit.server.git.AsyncReceiveCommits;
import com.google.gerrit.server.git.ReceiveCommits;
import com.google.gerrit.server.git.ReceivePackInitializer;
import com.google.gerrit.server.git.SearchingChangeCacheImpl;
import com.google.gerrit.server.git.TagCache;
import com.google.gerrit.server.git.TransferConfig;
import com.google.gerrit.server.git.VisibleRefFilter;
import com.google.gerrit.server.git.validators.UploadValidators;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.gerrit.server.project.ProjectControl;
import com.google.gerrit.server.util.RequestContext;
import com.google.gerrit.server.util.RequestScopePropagator;
import com.google.gerrit.server.util.ThreadLocalRequestContext;
import com.google.gerrit.server.util.ThreadLocalRequestScopePropagator;
import com.google.gwtorm.server.SchemaFactory;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.OutOfScopeException;
import com.google.inject.Provider;
import com.google.inject.Provides;
import com.google.inject.Scope;
import com.google.inject.servlet.RequestScoped;
import com.google.inject.util.Providers;
import java.io.IOException;
import java.net.SocketAddress;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.PostReceiveHook;
import org.eclipse.jgit.transport.PostReceiveHookChain;
import org.eclipse.jgit.transport.PreUploadHook;
import org.eclipse.jgit.transport.PreUploadHookChain;
import org.eclipse.jgit.transport.ReceivePack;
import org.eclipse.jgit.transport.TestProtocol;
import org.eclipse.jgit.transport.UploadPack;
import org.eclipse.jgit.transport.resolver.ReceivePackFactory;
import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException;
import org.eclipse.jgit.transport.resolver.UploadPackFactory;

class InProcessProtocol extends TestProtocol<Context> {
  static Module module() {
    return new AbstractModule() {
      @Override
      public void configure() {
        install(new GerritRequestModule());
        bind(RequestScopePropagator.class).to(Propagator.class);
        bindScope(RequestScoped.class, InProcessProtocol.REQUEST);
      }

      @Provides
      @RemotePeer
      SocketAddress getSocketAddress() {
        // TODO(dborowitz): Could potentially fake this with thread ID or
        // something.
        throw new OutOfScopeException("No remote peer in acceptance tests");
      }
    };
  }

  private static final Scope REQUEST =
      new Scope() {
        @Override
        public <T> Provider<T> scope(final Key<T> key, final Provider<T> creator) {
          return new Provider<T>() {
            @Override
            public T get() {
              Context ctx = current.get();
              if (ctx == null) {
                throw new OutOfScopeException("Not in TestProtocol scope");
              }
              return ctx.get(key, creator);
            }

            @Override
            public String toString() {
              return String.format("%s[%s]", creator, REQUEST);
            }
          };
        }

        @Override
        public String toString() {
          return "InProcessProtocol.REQUEST";
        }
      };

  private static class Propagator extends ThreadLocalRequestScopePropagator<Context> {
    @Inject
    Propagator(
        ThreadLocalRequestContext local,
        Provider<RequestScopedReviewDbProvider> dbProviderProvider) {
      super(REQUEST, current, local, dbProviderProvider);
    }

    @Override
    protected Context continuingContext(Context ctx) {
      return ctx.newContinuingContext();
    }
  }

  private static final ThreadLocal<Context> current = new ThreadLocal<>();

  // TODO(dborowitz): Merge this with AcceptanceTestRequestScope.
  /**
   * Multi-purpose session/context object.
   *
   * <p>Confusingly, Gerrit has two ideas of what a "context" object is: one for Guice {@link
   * RequestScoped}, and one for its own simplified version of request scoping using {@link
   * ThreadLocalRequestContext}. This class provides both, in essence just delegating the {@code
   * ThreadLocalRequestContext} scoping to the Guice scoping mechanism.
   *
   * <p>It is also used as the session type for {@code UploadPackFactory} and {@code
   * ReceivePackFactory}, since, after all, it encapsulates all the information about a single
   * request.
   */
  static class Context implements RequestContext {
    private static final Key<RequestScopedReviewDbProvider> DB_KEY =
        Key.get(RequestScopedReviewDbProvider.class);
    private static final Key<RequestCleanup> RC_KEY = Key.get(RequestCleanup.class);
    private static final Key<CurrentUser> USER_KEY = Key.get(CurrentUser.class);

    private final SchemaFactory<ReviewDb> schemaFactory;
    private final IdentifiedUser.GenericFactory userFactory;
    private final Account.Id accountId;
    private final Project.NameKey project;
    private final RequestCleanup cleanup;
    private final Map<Key<?>, Object> map;

    Context(
        SchemaFactory<ReviewDb> schemaFactory,
        IdentifiedUser.GenericFactory userFactory,
        Account.Id accountId,
        Project.NameKey project) {
      this.schemaFactory = schemaFactory;
      this.userFactory = userFactory;
      this.accountId = accountId;
      this.project = project;
      map = new HashMap<>();
      cleanup = new RequestCleanup();
      map.put(DB_KEY, new RequestScopedReviewDbProvider(schemaFactory, Providers.of(cleanup)));
      map.put(RC_KEY, cleanup);

      IdentifiedUser user = userFactory.create(accountId);
      user.setAccessPath(AccessPath.GIT);
      map.put(USER_KEY, user);
    }

    private Context newContinuingContext() {
      return new Context(schemaFactory, userFactory, accountId, project);
    }

    @Override
    public CurrentUser getUser() {
      return get(USER_KEY, null);
    }

    @Override
    public Provider<ReviewDb> getReviewDbProvider() {
      return get(DB_KEY, null);
    }

    private synchronized <T> T get(Key<T> key, Provider<T> creator) {
      @SuppressWarnings("unchecked")
      T t = (T) map.get(key);
      if (t == null) {
        t = creator.get();
        map.put(key, t);
      }
      return t;
    }
  }

  private static class Upload implements UploadPackFactory<Context> {
    private final Provider<ReviewDb> dbProvider;
    private final Provider<CurrentUser> userProvider;
    private final TagCache tagCache;
    @Nullable private final SearchingChangeCacheImpl changeCache;
    private final ProjectControl.GenericFactory projectControlFactory;
    private final ChangeNotes.Factory changeNotesFactory;
    private final TransferConfig transferConfig;
    private final DynamicSet<PreUploadHook> preUploadHooks;
    private final UploadValidators.Factory uploadValidatorsFactory;
    private final ThreadLocalRequestContext threadContext;

    @Inject
    Upload(
        Provider<ReviewDb> dbProvider,
        Provider<CurrentUser> userProvider,
        TagCache tagCache,
        @Nullable SearchingChangeCacheImpl changeCache,
        ProjectControl.GenericFactory projectControlFactory,
        ChangeNotes.Factory changeNotesFactory,
        TransferConfig transferConfig,
        DynamicSet<PreUploadHook> preUploadHooks,
        UploadValidators.Factory uploadValidatorsFactory,
        ThreadLocalRequestContext threadContext) {
      this.dbProvider = dbProvider;
      this.userProvider = userProvider;
      this.tagCache = tagCache;
      this.changeCache = changeCache;
      this.projectControlFactory = projectControlFactory;
      this.changeNotesFactory = changeNotesFactory;
      this.transferConfig = transferConfig;
      this.preUploadHooks = preUploadHooks;
      this.uploadValidatorsFactory = uploadValidatorsFactory;
      this.threadContext = threadContext;
    }

    @Override
    public UploadPack create(Context req, final Repository repo)
        throws ServiceNotAuthorizedException {
      // Set the request context, but don't bother unsetting, since we don't
      // have an easy way to run code when this instance is done being used.
      // Each operation is run in its own thread, so we don't need to recover
      // its original context anyway.
      threadContext.setContext(req);
      current.set(req);
      try {
        ProjectControl ctl = projectControlFactory.controlFor(req.project, userProvider.get());
        if (!ctl.canRunUploadPack()) {
          throw new ServiceNotAuthorizedException();
        }

        UploadPack up = new UploadPack(repo);
        up.setPackConfig(transferConfig.getPackConfig());
        up.setTimeout(transferConfig.getTimeout());
        up.setAdvertiseRefsHook(
            new VisibleRefFilter(
                tagCache, changeNotesFactory, changeCache, repo, ctl, dbProvider.get(), true));
        List<PreUploadHook> hooks = Lists.newArrayList(preUploadHooks);
        hooks.add(uploadValidatorsFactory.create(ctl.getProject(), repo, "localhost-test"));
        up.setPreUploadHook(PreUploadHookChain.newChain(hooks));
        return up;
      } catch (NoSuchProjectException | IOException e) {
        throw new RuntimeException(e);
      }
    }
  }

  private static class Receive implements ReceivePackFactory<Context> {
    private final Provider<CurrentUser> userProvider;
    private final ProjectControl.GenericFactory projectControlFactory;
    private final AsyncReceiveCommits.Factory factory;
    private final TransferConfig config;
    private final DynamicSet<ReceivePackInitializer> receivePackInitializers;
    private final DynamicSet<PostReceiveHook> postReceiveHooks;
    private final ThreadLocalRequestContext threadContext;

    @Inject
    Receive(
        Provider<CurrentUser> userProvider,
        ProjectControl.GenericFactory projectControlFactory,
        AsyncReceiveCommits.Factory factory,
        TransferConfig config,
        DynamicSet<ReceivePackInitializer> receivePackInitializers,
        DynamicSet<PostReceiveHook> postReceiveHooks,
        ThreadLocalRequestContext threadContext) {
      this.userProvider = userProvider;
      this.projectControlFactory = projectControlFactory;
      this.factory = factory;
      this.config = config;
      this.receivePackInitializers = receivePackInitializers;
      this.postReceiveHooks = postReceiveHooks;
      this.threadContext = threadContext;
    }

    @Override
    public ReceivePack create(final Context req, Repository db)
        throws ServiceNotAuthorizedException {
      // Set the request context, but don't bother unsetting, since we don't
      // have an easy way to run code when this instance is done being used.
      // Each operation is run in its own thread, so we don't need to recover
      // its original context anyway.
      threadContext.setContext(req);
      current.set(req);
      try {
        ProjectControl ctl = projectControlFactory.controlFor(req.project, userProvider.get());
        if (!ctl.canRunReceivePack()) {
          throw new ServiceNotAuthorizedException();
        }

        ReceiveCommits rc = factory.create(ctl, db).getReceiveCommits();
        ReceivePack rp = rc.getReceivePack();

        Capable r = rc.canUpload();
        if (r != Capable.OK) {
          throw new ServiceNotAuthorizedException();
        }

        rp.setRefLogIdent(ctl.getUser().asIdentifiedUser().newRefLogIdent());
        rp.setTimeout(config.getTimeout());
        rp.setMaxObjectSizeLimit(config.getMaxObjectSizeLimit());

        for (ReceivePackInitializer initializer : receivePackInitializers) {
          initializer.init(ctl.getProject().getNameKey(), rp);
        }

        rp.setPostReceiveHook(PostReceiveHookChain.newChain(Lists.newArrayList(postReceiveHooks)));
        return rp;
      } catch (NoSuchProjectException | IOException e) {
        throw new RuntimeException(e);
      }
    }
  }

  @Inject
  InProcessProtocol(Upload uploadPackFactory, Receive receivePackFactory) {
    super(uploadPackFactory, receivePackFactory);
  }
}
