// Copyright (C) 2014 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.change;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.gerrit.server.ioutil.BasicSerialization.readString;
import static com.google.gerrit.server.ioutil.BasicSerialization.writeString;
import static org.eclipse.jgit.lib.ObjectIdSerialization.readNotNull;
import static org.eclipse.jgit.lib.ObjectIdSerialization.writeNotNull;

import com.google.common.base.MoreObjects;
import com.google.common.cache.Cache;
import com.google.common.cache.Weigher;
import com.google.common.collect.ImmutableBiMap;
import com.google.common.util.concurrent.UncheckedExecutionException;
import com.google.gerrit.extensions.client.SubmitType;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.server.cache.CacheModule;
import com.google.gerrit.server.git.CodeReviewCommit;
import com.google.gerrit.server.git.CodeReviewCommit.CodeReviewRevWalk;
import com.google.gerrit.server.git.strategy.SubmitDryRun;
import com.google.inject.Inject;
import com.google.inject.Module;
import com.google.inject.Singleton;
import com.google.inject.name.Named;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Singleton
public class MergeabilityCacheImpl implements MergeabilityCache {
  private static final Logger log = LoggerFactory.getLogger(MergeabilityCacheImpl.class);

  private static final String CACHE_NAME = "mergeability";

  public static final ImmutableBiMap<SubmitType, Character> SUBMIT_TYPES =
      new ImmutableBiMap.Builder<SubmitType, Character>()
          .put(SubmitType.FAST_FORWARD_ONLY, 'F')
          .put(SubmitType.MERGE_IF_NECESSARY, 'M')
          .put(SubmitType.REBASE_ALWAYS, 'P')
          .put(SubmitType.REBASE_IF_NECESSARY, 'R')
          .put(SubmitType.MERGE_ALWAYS, 'A')
          .put(SubmitType.CHERRY_PICK, 'C')
          .build();

  static {
    checkState(
        SUBMIT_TYPES.size() == SubmitType.values().length,
        "SubmitType <-> char BiMap needs updating");
  }

  public static Module module() {
    return new CacheModule() {
      @Override
      protected void configure() {
        persist(CACHE_NAME, EntryKey.class, Boolean.class)
            .maximumWeight(1 << 20)
            .weigher(MergeabilityWeigher.class);
        bind(MergeabilityCache.class).to(MergeabilityCacheImpl.class);
      }
    };
  }

  public static ObjectId toId(Ref ref) {
    return ref != null && ref.getObjectId() != null ? ref.getObjectId() : ObjectId.zeroId();
  }

  public static class EntryKey implements Serializable {
    private static final long serialVersionUID = 1L;

    private ObjectId commit;
    private ObjectId into;
    private SubmitType submitType;
    private String mergeStrategy;

    public EntryKey(ObjectId commit, ObjectId into, SubmitType submitType, String mergeStrategy) {
      this.commit = checkNotNull(commit, "commit");
      this.into = checkNotNull(into, "into");
      this.submitType = checkNotNull(submitType, "submitType");
      this.mergeStrategy = checkNotNull(mergeStrategy, "mergeStrategy");
    }

    public ObjectId getCommit() {
      return commit;
    }

    public ObjectId getInto() {
      return into;
    }

    public SubmitType getSubmitType() {
      return submitType;
    }

    public String getMergeStrategy() {
      return mergeStrategy;
    }

    @Override
    public boolean equals(Object o) {
      if (o instanceof EntryKey) {
        EntryKey k = (EntryKey) o;
        return commit.equals(k.commit)
            && into.equals(k.into)
            && submitType == k.submitType
            && mergeStrategy.equals(k.mergeStrategy);
      }
      return false;
    }

    @Override
    public int hashCode() {
      return Objects.hash(commit, into, submitType, mergeStrategy);
    }

    @Override
    public String toString() {
      return MoreObjects.toStringHelper(this)
          .add("commit", commit.name())
          .add("into", into.name())
          .addValue(submitType)
          .addValue(mergeStrategy)
          .toString();
    }

    private void writeObject(ObjectOutputStream out) throws IOException {
      writeNotNull(out, commit);
      writeNotNull(out, into);
      Character c = SUBMIT_TYPES.get(submitType);
      if (c == null) {
        throw new IOException("Invalid submit type: " + submitType);
      }
      out.writeChar(c);
      writeString(out, mergeStrategy);
    }

    private void readObject(ObjectInputStream in) throws IOException {
      commit = readNotNull(in);
      into = readNotNull(in);
      char t = in.readChar();
      submitType = SUBMIT_TYPES.inverse().get(t);
      if (submitType == null) {
        throw new IOException("Invalid submit type code: " + t);
      }
      mergeStrategy = readString(in);
    }
  }

  public static class MergeabilityWeigher implements Weigher<EntryKey, Boolean> {
    @Override
    public int weigh(EntryKey k, Boolean v) {
      return 16
          + 2 * (16 + 20)
          + 3 * 8 // Size of EntryKey, 64-bit JVM.
          + 8; // Size of Boolean.
    }
  }

  private final SubmitDryRun submitDryRun;
  private final Cache<EntryKey, Boolean> cache;

  @Inject
  MergeabilityCacheImpl(
      SubmitDryRun submitDryRun, @Named(CACHE_NAME) Cache<EntryKey, Boolean> cache) {
    this.submitDryRun = submitDryRun;
    this.cache = cache;
  }

  @Override
  public boolean get(
      ObjectId commit,
      Ref intoRef,
      SubmitType submitType,
      String mergeStrategy,
      Branch.NameKey dest,
      Repository repo) {
    ObjectId into = intoRef != null ? intoRef.getObjectId() : ObjectId.zeroId();
    EntryKey key = new EntryKey(commit, into, submitType, mergeStrategy);
    try {
      return cache.get(
          key,
          () -> {
            if (key.into.equals(ObjectId.zeroId())) {
              return true; // Assume yes on new branch.
            }
            try (CodeReviewRevWalk rw = CodeReviewCommit.newRevWalk(repo)) {
              Set<RevCommit> accepted = SubmitDryRun.getAlreadyAccepted(repo, rw);
              accepted.add(rw.parseCommit(key.into));
              accepted.addAll(Arrays.asList(rw.parseCommit(key.commit).getParents()));
              return submitDryRun.run(
                  key.submitType, repo, rw, dest, key.into, key.commit, accepted);
            }
          });
    } catch (ExecutionException | UncheckedExecutionException e) {
      log.error(
          "Error checking mergeability of {} into {} ({})",
          key.commit.name(),
          key.into.name(),
          key.submitType.name(),
          e.getCause());
      return false;
    }
  }

  @Override
  public Boolean getIfPresent(
      ObjectId commit, Ref intoRef, SubmitType submitType, String mergeStrategy) {
    return cache.getIfPresent(new EntryKey(commit, toId(intoRef), submitType, mergeStrategy));
  }
}
