// Copyright (C) 2009 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.reviewdb.client.Project.NameKey;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.gerrit.server.project.ProjectControl;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.SchemaFactory;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;

import com.jcraft.jsch.JSchException;

import org.eclipse.jgit.errors.NoRemoteRepositoryException;
import org.eclipse.jgit.errors.NotSupportedException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.errors.TransportException;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.CredentialsProvider;
import org.eclipse.jgit.transport.FetchConnection;
import org.eclipse.jgit.transport.PushResult;
import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.transport.RemoteConfig;
import org.eclipse.jgit.transport.RemoteRefUpdate;
import org.eclipse.jgit.transport.Transport;
import org.eclipse.jgit.transport.URIish;
import org.slf4j.Logger;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * A push to remote operation started by {@link ReplicationQueue}.
 * <p>
 * Instance members are protected by the lock within PushQueue. Callers must
 * take that lock to ensure they are working with a current view of the object.
 */
class PushOp implements ProjectRunnable {
  interface Factory {
    PushOp create(Project.NameKey d, URIish u);
  }

  private static final Logger log = PushReplication.log;
  static final String ALL_REFS = "..all..";

  private final GitRepositoryManager repoManager;
  private final SchemaFactory<ReviewDb> schema;
  private final PushReplication.ReplicationConfig pool;
  private final RemoteConfig config;
  private final CredentialsProvider credentialsProvider;
  private final TagCache tagCache;

  private final Set<String> delta = new HashSet<String>();
  private final Project.NameKey projectName;
  private final URIish uri;
  private boolean pushAllRefs;

  private Repository db;

  /**
   * It indicates if the current instance is in fact retrying to push.
   */
  private boolean retrying;

  private boolean canceled;

  @Inject
  PushOp(final GitRepositoryManager grm, final SchemaFactory<ReviewDb> s,
      final PushReplication.ReplicationConfig p, final RemoteConfig c,
      final SecureCredentialsProvider.Factory cpFactory,
      final TagCache tc,
      @Assisted final Project.NameKey d, @Assisted final URIish u) {
    repoManager = grm;
    schema = s;
    pool = p;
    config = c;
    credentialsProvider = cpFactory.create(c.getName());
    tagCache = tc;
    projectName = d;
    uri = u;
  }

  public boolean isRetrying() {
    return retrying;
  }

  public void setToRetry() {
    retrying = true;
  }

  public void cancel() {
    canceled = true;
  }

  public boolean wasCanceled() {
    return canceled;
  }

  URIish getURI() {
    return uri;
  }

  void addRef(final String ref) {
    if (ALL_REFS.equals(ref)) {
      delta.clear();
      pushAllRefs = true;
    } else if (!pushAllRefs) {
      delta.add(ref);
    }
  }

  public Set<String> getRefs() {
    final Set<String> refs;

    if (pushAllRefs) {
      refs = new HashSet<String>(1);
      refs.add(ALL_REFS);
    } else {
      refs = delta;
    }

    return refs;
  }

  public void addRefs(Set<String> refs) {
    if (!pushAllRefs) {
      for (String ref : refs) {
        addRef(ref);
      }
    }
  }

  public void run() {
    PerThreadRequestScope ctx = new PerThreadRequestScope();
    PerThreadRequestScope old = PerThreadRequestScope.set(ctx);
    try {
      runPushOperation();
    } finally {
      PerThreadRequestScope.set(old);
    }
  }

  private void runPushOperation() {
    // Lock the queue, and remove ourselves, so we can't be modified once
    // we start replication (instead a new instance, with the same URI, is
    // created and scheduled for a future point in time.)
    //
    pool.notifyStarting(this);

    // It should only verify if it was canceled after calling notifyStarting,
    // since the canceled flag would be set locking the queue.
    if (!canceled) {
      try {
        db = repoManager.openRepository(projectName);
        runImpl();
      } catch (RepositoryNotFoundException e) {
        log.error("Cannot replicate " + projectName + "; " + e.getMessage());

      } catch (NoRemoteRepositoryException e) {
        log.error("Cannot replicate to " + uri + "; repository not found");

      } catch (NotSupportedException e) {
        log.error("Cannot replicate to " + uri, e);

      } catch (TransportException e) {
        final Throwable cause = e.getCause();
        if (cause instanceof JSchException
            && cause.getMessage().startsWith("UnknownHostKey:")) {
          log.error("Cannot replicate to " + uri + ": " + cause.getMessage());
        } else {
          log.error("Cannot replicate to " + uri, e);
        }

        // The remote push operation should be retried.
        pool.reschedule(this);
      } catch (IOException e) {
        log.error("Cannot replicate to " + uri, e);

      } catch (RuntimeException e) {
        log.error("Unexpected error during replication to " + uri, e);

      } catch (Error e) {
        log.error("Unexpected error during replication to " + uri, e);

      } finally {
        if (db != null) {
          db.close();
        }
      }
    }
  }

  @Override
  public String toString() {
    return "push " + uri;
  }

  private void runImpl() throws IOException {
    final Transport tn = Transport.open(db, uri);
    final PushResult res;
    try {
      res = pushVia(tn);
    } finally {
      try {
        tn.close();
      } catch (Throwable e2) {
        log.warn("Unexpected error while closing " + uri, e2);
      }
    }

    for (final RemoteRefUpdate u : res.getRemoteUpdates()) {
      switch (u.getStatus()) {
        case OK:
        case UP_TO_DATE:
        case NON_EXISTING:
          break;

        case NOT_ATTEMPTED:
        case AWAITING_REPORT:
        case REJECTED_NODELETE:
        case REJECTED_NONFASTFORWARD:
        case REJECTED_REMOTE_CHANGED:
          log.error("Failed replicate of " + u.getRemoteName() + " to " + uri
              + ": status " + u.getStatus().name());
          break;

        case REJECTED_OTHER_REASON:
          if ("non-fast-forward".equals(u.getMessage())) {
            log.error("Failed replicate of " + u.getRemoteName() + " to " + uri
                + ", remote rejected non-fast-forward push."
                + "  Check receive.denyNonFastForwards variable in config file"
                + " of destination repository.");
          } else {
            log.error("Failed replicate of " + u.getRemoteName() + " to " + uri
                + ", reason: " + u.getMessage());
          }
          break;
      }
    }
  }

  private PushResult pushVia(final Transport tn) throws IOException,
      NotSupportedException, TransportException {
    tn.applyConfig(config);
    tn.setCredentialsProvider(credentialsProvider);

    final List<RemoteRefUpdate> todo = generateUpdates(tn);
    if (todo.isEmpty()) {
      // If we have no commands selected, we have nothing to do.
      // Calling JGit at this point would just redo the work we
      // already did, and come up with the same answer. Instead
      // send back an empty result.
      //
      return new PushResult();
    }

    return tn.push(NullProgressMonitor.INSTANCE, todo);
  }

  private List<RemoteRefUpdate> generateUpdates(final Transport tn)
      throws IOException {
    final ProjectControl pc;
    try {
      pc = pool.controlFor(projectName);
    } catch (NoSuchProjectException e) {
      return Collections.emptyList();
    }

    Map<String, Ref> local = db.getAllRefs();
    if (!pc.allRefsAreVisible()) {
      if (!pushAllRefs) {
        // If we aren't mirroring, reduce the space we need to filter
        // to only the references we will update during this operation.
        //
        Map<String, Ref> n = new HashMap<String, Ref>();
        for (String src : delta) {
          Ref r = local.get(src);
          if (r != null) {
            n.put(src, r);
          }
        }
        local = n;
      }

      final ReviewDb meta;
      try {
        meta = schema.open();
      } catch (OrmException e) {
        log.error("Cannot read database to replicate to " + projectName, e);
        return Collections.emptyList();
      }
      try {
        local = new VisibleRefFilter(tagCache, db, pc, meta, true).filter(local, true);
      } finally {
        meta.close();
      }
    }

    final boolean noPerms = !pool.isReplicatePermissions();
    final List<RemoteRefUpdate> cmds = new ArrayList<RemoteRefUpdate>();
    if (pushAllRefs) {
      final Map<String, Ref> remote = listRemote(tn);

      for (final Ref src : local.values()) {
        if (noPerms && GitRepositoryManager.REF_CONFIG.equals(src.getName())) {
          continue;
        }

        final RefSpec spec = matchSrc(src.getName());
        if (spec != null) {
          final Ref dst = remote.get(spec.getDestination());
          if (dst == null || !src.getObjectId().equals(dst.getObjectId())) {
            // Doesn't exist yet, or isn't the same value, request to push.
            //
            send(cmds, spec, src);
          }
        }
      }

      if (config.isMirror()) {
        for (final Ref ref : remote.values()) {
          if (!Constants.HEAD.equals(ref.getName())) {
            final RefSpec spec = matchDst(ref.getName());
            if (spec != null && !local.containsKey(spec.getSource())) {
              // No longer on local side, request removal.
              //
              delete(cmds, spec);
            }
          }
        }
      }

    } else {
      for (final String src : delta) {
        final RefSpec spec = matchSrc(src);
        if (spec != null) {
          // If the ref still exists locally, send it, otherwise delete it.
          //
          Ref srcRef = local.get(src);
          if (srcRef != null &&
              !(noPerms && GitRepositoryManager.REF_CONFIG.equals(src))) {
            send(cmds, spec, srcRef);
          } else if (config.isMirror()) {
            delete(cmds, spec);
          }
        }
      }
    }

    return cmds;
  }

  private Map<String, Ref> listRemote(final Transport tn)
      throws NotSupportedException, TransportException {
    final FetchConnection fc = tn.openFetch();
    try {
      return fc.getRefsMap();
    } finally {
      fc.close();
    }
  }

  private RefSpec matchSrc(final String ref) {
    for (final RefSpec s : config.getPushRefSpecs()) {
      if (s.matchSource(ref)) {
        return s.expandFromSource(ref);
      }
    }
    return null;
  }

  private RefSpec matchDst(final String ref) {
    for (final RefSpec s : config.getPushRefSpecs()) {
      if (s.matchDestination(ref)) {
        return s.expandFromDestination(ref);
      }
    }
    return null;
  }

  private void send(final List<RemoteRefUpdate> cmds, final RefSpec spec,
      final Ref src) throws IOException {
    final String dst = spec.getDestination();
    final boolean force = spec.isForceUpdate();
    cmds.add(new RemoteRefUpdate(db, src, dst, force, null, null));
  }

  private void delete(final List<RemoteRefUpdate> cmds, final RefSpec spec)
      throws IOException {
    final String dst = spec.getDestination();
    final boolean force = spec.isForceUpdate();
    cmds.add(new RemoteRefUpdate(db, (Ref) null, dst, force, null, null));
  }

  @Override
  public NameKey getProjectNameKey() {
    return projectName;
  }

  @Override
  public String getRemoteName() {
    return config.getName();
  }

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