// Copyright (C) 2016 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.patch;

import static com.google.gerrit.server.ioutil.BasicSerialization.readVarInt32;
import static com.google.gerrit.server.ioutil.BasicSerialization.writeVarInt32;

import com.google.auto.value.AutoValue;
import com.google.gerrit.server.cache.proto.Cache.FileDiffOutputProto;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Optional;

/** Relation between the old and new commits used in the diff. */
@AutoValue
public abstract class ComparisonType {

  /**
   * 1-based parent. Available if the old commit is the parent of the new commit and old commit is
   * not the auto-merge. If set to 0, then comparison is for a root commit.
   */
  abstract Optional<Integer> parentNum();

  abstract boolean autoMerge();

  public static ComparisonType againstOtherPatchSet() {
    return new AutoValue_ComparisonType(Optional.empty(), false);
  }

  public static ComparisonType againstParent(int parentNum) {
    return new AutoValue_ComparisonType(Optional.of(parentNum), false);
  }

  public static ComparisonType againstAutoMerge() {
    return new AutoValue_ComparisonType(Optional.empty(), true);
  }

  public static ComparisonType againstRoot() {
    return new AutoValue_ComparisonType(Optional.of(0), false);
  }

  private static ComparisonType create(Optional<Integer> parent, boolean automerge) {
    return new AutoValue_ComparisonType(parent, automerge);
  }

  public boolean isAgainstParentOrAutoMerge() {
    return isAgainstParent() || isAgainstAutoMerge();
  }

  public boolean isAgainstParent() {
    return parentNum().isPresent();
  }

  public boolean isAgainstAutoMerge() {
    return autoMerge();
  }

  public Optional<Integer> getParentNum() {
    return parentNum();
  }

  void writeTo(OutputStream out) throws IOException {
    writeVarInt32(out, isAgainstParent() ? parentNum().get() : 0);
    writeVarInt32(out, autoMerge() ? 1 : 0);
  }

  static ComparisonType readFrom(InputStream in) throws IOException {
    int p = readVarInt32(in);
    Optional<Integer> parentNum = p > 0 ? Optional.of(p) : Optional.empty();
    boolean autoMerge = readVarInt32(in) != 0;
    return create(parentNum, autoMerge);
  }

  public FileDiffOutputProto.ComparisonType toProto() {
    FileDiffOutputProto.ComparisonType.Builder builder =
        FileDiffOutputProto.ComparisonType.newBuilder().setAutoMerge(autoMerge());
    if (parentNum().isPresent()) {
      builder.setParentNum(parentNum().get());
    }
    return builder.build();
  }

  public static ComparisonType fromProto(FileDiffOutputProto.ComparisonType proto) {
    Optional<Integer> parentNum = Optional.empty();
    if (proto.hasField(FileDiffOutputProto.ComparisonType.getDescriptor().findFieldByNumber(1))) {
      parentNum = Optional.of(proto.getParentNum());
    }
    return create(parentNum, proto.getAutoMerge());
  }
}
