//  Copyright (C) 2020 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.gitfilediff;

import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.collect.ImmutableList;
import com.google.gerrit.entities.Patch;
import com.google.gerrit.entities.Patch.PatchType;
import java.util.Optional;
import org.eclipse.jgit.patch.CombinedFileHeader;
import org.eclipse.jgit.patch.FileHeader;
import org.eclipse.jgit.util.IntList;
import org.eclipse.jgit.util.RawParseUtils;

/** A utility class for the {@link FileHeader} JGit object */
public class FileHeaderUtil {
  private static final Byte NUL = '\0';

  /**
   * The maximum number of characters to lookup in the binary file {@link FileHeader}. This is used
   * to scan the file header for the occurrence of the {@link #NUL} character.
   *
   * <p>This limit assumes a uniform distribution of all characters, hence the probability of the
   * occurrence of each character = (1 / 256). We want to find the limit that makes the prob. of
   * finding {@link #NUL} > 0.999. 1 - (255 / 256) ^ N > 0.999 yields N = 1766. We set the limit to
   * this value multiplied by 10 for more confidence.
   */
  private static final int BIN_FILE_MAX_SCAN_LIMIT = 20000;

  /** Converts the {@link FileHeader} parameter to a String representation. */
  static String toString(FileHeader header) {
    return new String(FileHeaderUtil.toByteArray(header), UTF_8);
  }

  /** Converts the {@link FileHeader} parameter to a byte array. */
  static byte[] toByteArray(FileHeader header) {
    int end = getEndOffset(header);
    if (header.getStartOffset() == 0 && end == header.getBuffer().length) {
      return header.getBuffer();
    }

    final byte[] buf = new byte[end - header.getStartOffset()];
    System.arraycopy(header.getBuffer(), header.getStartOffset(), buf, 0, buf.length);
    return buf;
  }

  /** Splits the {@code FileHeader} string to a list of strings, one string per header line. */
  public static ImmutableList<String> getHeaderLines(FileHeader fileHeader) {
    String fileHeaderString = toString(fileHeader);
    return getHeaderLines(fileHeaderString);
  }

  public static ImmutableList<String> getHeaderLines(String header) {
    return getHeaderLines(header.getBytes(UTF_8));
  }

  static ImmutableList<String> getHeaderLines(byte[] header) {
    final IntList lineStartOffsets = RawParseUtils.lineMap(header, 0, header.length);
    final ImmutableList.Builder<String> headerLines =
        ImmutableList.builderWithExpectedSize(lineStartOffsets.size() - 1);
    for (int i = 1; i < lineStartOffsets.size() - 1; i++) {
      final int b = lineStartOffsets.get(i);
      int e = lineStartOffsets.get(i + 1);
      if (header[e - 1] == '\n') {
        e--;
      }
      headerLines.add(RawParseUtils.decode(UTF_8, header, b, e));
    }
    return headerLines.build();
  }

  /**
   * Returns the old file path associated with the {@link FileHeader}, or empty if the file is
   * {@link com.google.gerrit.entities.Patch.ChangeType#ADDED} or {@link
   * com.google.gerrit.entities.Patch.ChangeType#REWRITE}.
   */
  public static Optional<String> getOldPath(FileHeader header) {
    Patch.ChangeType changeType = getChangeType(header);
    switch (changeType) {
      case DELETED:
      case COPIED:
      case RENAMED:
      case MODIFIED:
        return Optional.of(header.getOldPath());

      case ADDED:
      case REWRITE:
        return Optional.empty();
    }
    return Optional.empty();
  }

  /**
   * Returns the new file path associated with the {@link FileHeader}, or empty if the file is
   * {@link com.google.gerrit.entities.Patch.ChangeType#DELETED}.
   */
  public static Optional<String> getNewPath(FileHeader header) {
    Patch.ChangeType changeType = getChangeType(header);
    switch (changeType) {
      case DELETED:
        return Optional.empty();

      case ADDED:
      case MODIFIED:
      case REWRITE:
      case COPIED:
      case RENAMED:
        return Optional.of(header.getNewPath());
    }
    return Optional.empty();
  }

  /** Returns the change type associated with the file header. */
  public static Patch.ChangeType getChangeType(FileHeader header) {
    // In Gerrit, we define our own entities  of the JGit entities, so that we have full control
    // over their behaviors (e.g. making sure that these entities are immutable so that we can add
    // them as fields of keys / values of persisted caches).

    // TODO(ghareeb): remove the dead code of the value REWRITE and all its handling
    switch (header.getChangeType()) {
      case ADD:
        return Patch.ChangeType.ADDED;
      case MODIFY:
        return Patch.ChangeType.MODIFIED;
      case DELETE:
        return Patch.ChangeType.DELETED;
      case RENAME:
        return Patch.ChangeType.RENAMED;
      case COPY:
        return Patch.ChangeType.COPIED;
      default:
        throw new IllegalArgumentException("Unsupported type " + header.getChangeType());
    }
  }

  public static PatchType getPatchType(FileHeader header) {
    PatchType patchType;

    switch (header.getPatchType()) {
      case UNIFIED:
        patchType = Patch.PatchType.UNIFIED;
        break;
      case GIT_BINARY:
      case BINARY:
        patchType = Patch.PatchType.BINARY;
        break;
      default:
        throw new IllegalArgumentException("Unsupported type " + header.getPatchType());
    }

    if (patchType != PatchType.BINARY) {
      byte[] buf = header.getBuffer();
      // TODO(ghareeb): should we adjust the max limit threshold?
      // JGit sometimes misses the detection of binary files. In this case we look into the file
      // header for the occurrence of NUL characters, which is a definite signal that the file is
      // binary. We limit the number of characters to lookup to avoid performance bottlenecks.
      for (int ptr = header.getStartOffset();
          ptr < Math.min(header.getEndOffset(), BIN_FILE_MAX_SCAN_LIMIT);
          ptr++) {
        if (buf[ptr] == NUL) {
          // It's really binary, but Git couldn't see the nul early enough to realize its binary,
          // and instead produced the diff.
          //
          // Force it to be a binary; it really should have been that.
          return PatchType.BINARY;
        }
      }
    }
    return patchType;
  }

  /**
   * Returns the end offset of the diff header line of the {@code FileHeader parameter} before the
   * appearance of any file edits (diff hunks).
   */
  private static int getEndOffset(FileHeader fileHeader) {
    if (fileHeader instanceof CombinedFileHeader) {
      return fileHeader.getEndOffset();
    }
    if (!fileHeader.getHunks().isEmpty()) {
      return fileHeader.getHunks().get(0).getStartOffset();
    }
    return fileHeader.getEndOffset();
  }
}
