// 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.notedb;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.gerrit.server.PatchLineCommentsUtil.PLC_ORDER;
import static com.google.gerrit.server.notedb.ChangeNoteUtil.GERRIT_PLACEHOLDER_HOST;
import static com.google.gerrit.server.notedb.ChangeNotes.parseException;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;

import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.primitives.Ints;
import com.google.gerrit.common.data.AccountInfo;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.CommentRange;
import com.google.gerrit.reviewdb.client.Patch;
import com.google.gerrit.reviewdb.client.PatchLineComment;
import com.google.gerrit.reviewdb.client.PatchLineComment.Status;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.RevId;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.PatchLineCommentsUtil;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.config.AnonymousCowardName;
import com.google.inject.Inject;
import com.google.inject.Singleton;

import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.notes.Note;
import org.eclipse.jgit.notes.NoteMap;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.util.GitDateFormatter;
import org.eclipse.jgit.util.GitDateFormatter.Format;
import org.eclipse.jgit.util.GitDateParser;
import org.eclipse.jgit.util.MutableInteger;
import org.eclipse.jgit.util.QuotedString;
import org.eclipse.jgit.util.RawParseUtils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.nio.charset.Charset;
import java.sql.Timestamp;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;

/**
 * Utility functions to parse PatchLineComments out of a note byte array and
 * store a list of PatchLineComments in the form of a note (in a byte array).
 **/
@Singleton
public class CommentsInNotesUtil {
  private static final String AUTHOR = "Author";
  private static final String BASE_PATCH_SET = "Base-for-patch-set";
  private static final String COMMENT_RANGE = "Comment-range";
  private static final String FILE = "File";
  private static final String LENGTH = "Bytes";
  private static final String PARENT = "Parent";
  private static final String PATCH_SET = "Patch-set";
  private static final String REVISION = "Revision";
  private static final String UUID = "UUID";
  private static final int MAX_NOTE_SZ = 25 << 20;

  public static NoteMap parseCommentsFromNotes(Repository repo, String refName,
      RevWalk walk, Change.Id changeId,
      Multimap<RevId, PatchLineComment> comments,
      Status status)
      throws IOException, ConfigInvalidException {
    Ref ref = repo.getRefDatabase().exactRef(refName);
    if (ref == null) {
      return null;
    }

    ObjectReader reader = walk.getObjectReader();
    RevCommit commit = walk.parseCommit(ref.getObjectId());
    NoteMap noteMap = NoteMap.read(reader, commit);

    for (Note note : noteMap) {
      byte[] bytes =
          reader.open(note.getData(), OBJ_BLOB).getCachedBytes(MAX_NOTE_SZ);
      List<PatchLineComment> result = parseNote(bytes, changeId, status);
      if (result == null || result.isEmpty()) {
        continue;
      }
      comments.putAll(new RevId(note.name()), result);
    }
    return noteMap;
  }

  public static List<PatchLineComment> parseNote(byte[] note,
      Change.Id changeId, Status status) throws ConfigInvalidException {
    List<PatchLineComment> result = Lists.newArrayList();
    int sizeOfNote = note.length;
    Charset enc = RawParseUtils.parseEncoding(note);
    MutableInteger curr = new MutableInteger();
    curr.value = 0;

    boolean isForBase =
        (RawParseUtils.match(note, curr.value, PATCH_SET.getBytes(UTF_8))) < 0;

    PatchSet.Id psId = parsePsId(note, curr, changeId, enc,
        isForBase ? BASE_PATCH_SET : PATCH_SET);

    RevId revId =
        new RevId(parseStringField(note, curr, changeId, enc, REVISION));

    PatchLineComment c = null;
    while (curr.value < sizeOfNote) {
      String previousFileName = c == null ?
          null : c.getKey().getParentKey().getFileName();
      c = parseComment(note, curr, previousFileName, psId, revId,
          isForBase, enc, status);
      result.add(c);
    }
    return result;
  }

  public static String formatTime(PersonIdent ident, Timestamp t) {
    GitDateFormatter dateFormatter = new GitDateFormatter(Format.DEFAULT);
    // TODO(dborowitz): Use a ThreadLocal or use Joda.
    PersonIdent newIdent = new PersonIdent(ident, t);
    return dateFormatter.formatDate(newIdent);
  }

  private static PatchLineComment parseComment(byte[] note, MutableInteger curr,
      String currentFileName, PatchSet.Id psId, RevId revId, boolean isForBase,
      Charset enc, Status status)
          throws ConfigInvalidException {
    Change.Id changeId = psId.getParentKey();

    // Check if there is a new file.
    boolean newFile =
        (RawParseUtils.match(note, curr.value, FILE.getBytes(UTF_8))) != -1;
    if (newFile) {
      // If so, parse the new file name.
      currentFileName = parseFilename(note, curr, changeId, enc);
    } else if (currentFileName == null) {
      throw parseException(changeId, "could not parse %s", FILE);
    }

    CommentRange range = parseCommentRange(note, curr);
    if (range == null) {
      throw parseException(changeId, "could not parse %s", COMMENT_RANGE);
    }

    Timestamp commentTime = parseTimestamp(note, curr, changeId, enc);
    Account.Id aId = parseAuthor(note, curr, changeId, enc);

    boolean hasParent =
        (RawParseUtils.match(note, curr.value, PARENT.getBytes(enc))) != -1;
    String parentUUID = null;
    if (hasParent) {
      parentUUID = parseStringField(note, curr, changeId, enc, PARENT);
    }

    String uuid = parseStringField(note, curr, changeId, enc, UUID);
    int commentLength = parseCommentLength(note, curr, changeId, enc);

    String message = RawParseUtils.decode(
        enc, note, curr.value, curr.value + commentLength);
    checkResult(message, "message contents", changeId);

    PatchLineComment plc = new PatchLineComment(
        new PatchLineComment.Key(new Patch.Key(psId, currentFileName), uuid),
        range.getEndLine(), aId, parentUUID, commentTime);
    plc.setMessage(message);
    plc.setSide((short) (isForBase ? 0 : 1));
    if (range.getStartCharacter() != -1) {
      plc.setRange(range);
    }
    plc.setRevId(revId);
    plc.setStatus(status);

    curr.value = RawParseUtils.nextLF(note, curr.value + commentLength);
    curr.value = RawParseUtils.nextLF(note, curr.value);
    return plc;
  }

  private static String parseStringField(byte[] note, MutableInteger curr,
      Change.Id changeId, Charset enc, String fieldName)
      throws ConfigInvalidException {
    int endOfLine = RawParseUtils.nextLF(note, curr.value);
    checkHeaderLineFormat(note, curr, fieldName, enc, changeId);
    int startOfField = RawParseUtils.endOfFooterLineKey(note, curr.value) + 2;
    curr.value = endOfLine;
    return RawParseUtils.decode(enc, note, startOfField, endOfLine - 1);
  }

  /**
   * @return a comment range. If the comment range line in the note only has
   *    one number, we return a CommentRange with that one number as the end
   *    line and the other fields as -1. If the comment range line in the note
   *    contains a whole comment range, then we return a CommentRange with all
   *    fields set. If the line is not correctly formatted, return null.
   */
  private static CommentRange parseCommentRange(byte[] note, MutableInteger ptr) {
    CommentRange range = new CommentRange(-1, -1, -1, -1);

    int startLine = RawParseUtils.parseBase10(note, ptr.value, ptr);
    if (startLine == 0) {
      range.setEndLine(0);
      ptr.value += 1;
      return range;
    }

    if (note[ptr.value] == '\n') {
      range.setEndLine(startLine);
      ptr.value += 1;
      return range;
    } else if (note[ptr.value] == ':') {
      range.setStartLine(startLine);
      ptr.value += 1;
    } else {
      return null;
    }

    int startChar = RawParseUtils.parseBase10(note, ptr.value, ptr);
    if (startChar == 0) {
      return null;
    }
    if (note[ptr.value] == '-') {
      range.setStartCharacter(startChar);
      ptr.value += 1;
    } else {
      return null;
    }

    int endLine = RawParseUtils.parseBase10(note, ptr.value, ptr);
    if (endLine == 0) {
      return null;
    }
    if (note[ptr.value] == ':') {
      range.setEndLine(endLine);
      ptr.value += 1;
    } else {
      return null;
    }

    int endChar = RawParseUtils.parseBase10(note, ptr.value, ptr);
    if (endChar == 0) {
      return null;
    }
    if (note[ptr.value] == '\n') {
      range.setEndCharacter(endChar);
      ptr.value += 1;
    } else {
      return null;
    }
    return range;
  }

  private static PatchSet.Id parsePsId(byte[] note, MutableInteger curr,
      Change.Id changeId, Charset enc, String fieldName)
      throws ConfigInvalidException {
    checkHeaderLineFormat(note, curr, fieldName, enc, changeId);
    int startOfPsId =
        RawParseUtils.endOfFooterLineKey(note, curr.value) + 1;
    MutableInteger i = new MutableInteger();
    int patchSetId =
        RawParseUtils.parseBase10(note, startOfPsId, i);
    int endOfLine = RawParseUtils.nextLF(note, curr.value);
    if (i.value != endOfLine - 1) {
      throw parseException(changeId, "could not parse %s", fieldName);
    }
    checkResult(patchSetId, "patchset id", changeId);
    curr.value = endOfLine;
    return new PatchSet.Id(changeId, patchSetId);
  }

  private static String parseFilename(byte[] note, MutableInteger curr,
      Change.Id changeId, Charset enc) throws ConfigInvalidException {
    checkHeaderLineFormat(note, curr, FILE, enc, changeId);
    int startOfFileName =
        RawParseUtils.endOfFooterLineKey(note, curr.value) + 2;
    int endOfLine = RawParseUtils.nextLF(note, curr.value);
    curr.value = endOfLine;
    curr.value = RawParseUtils.nextLF(note, curr.value);
    return QuotedString.GIT_PATH.dequote(
        RawParseUtils.decode(enc, note, startOfFileName, endOfLine - 1));
  }

  private static Timestamp parseTimestamp(byte[] note, MutableInteger curr,
      Change.Id changeId, Charset enc)
      throws ConfigInvalidException {
    int endOfLine = RawParseUtils.nextLF(note, curr.value);
    Timestamp commentTime;
    String dateString =
        RawParseUtils.decode(enc, note, curr.value, endOfLine - 1);
    try {
      commentTime = new Timestamp(
          GitDateParser.parse(dateString, null, Locale.US).getTime());
    } catch (ParseException e) {
      throw new ConfigInvalidException("could not parse comment timestamp", e);
    }
    curr.value = endOfLine;
    return checkResult(commentTime, "comment timestamp", changeId);
  }

  private static Account.Id parseAuthor(byte[] note, MutableInteger curr,
      Change.Id changeId, Charset enc) throws ConfigInvalidException {
    checkHeaderLineFormat(note, curr, AUTHOR, enc, changeId);
    int startOfAccountId =
        RawParseUtils.endOfFooterLineKey(note, curr.value) + 2;
    PersonIdent ident =
        RawParseUtils.parsePersonIdent(note, startOfAccountId);
    Account.Id aId = parseIdent(ident, changeId);
    curr.value = RawParseUtils.nextLF(note, curr.value);
    return checkResult(aId, "comment author", changeId);
  }

  private static int parseCommentLength(byte[] note, MutableInteger curr,
      Change.Id changeId, Charset enc) throws ConfigInvalidException {
    checkHeaderLineFormat(note, curr, LENGTH, enc, changeId);
    int startOfLength =
        RawParseUtils.endOfFooterLineKey(note, curr.value) + 1;
    MutableInteger i = new MutableInteger();
    int commentLength =
        RawParseUtils.parseBase10(note, startOfLength, i);
    int endOfLine = RawParseUtils.nextLF(note, curr.value);
    if (i.value != endOfLine-1) {
      throw parseException(changeId, "could not parse %s", PATCH_SET);
    }
    curr.value = endOfLine;
    return checkResult(commentLength, "comment length", changeId);
  }

  private static <T> T checkResult(T o, String fieldName,
      Change.Id changeId) throws ConfigInvalidException {
    if (o == null) {
      throw parseException(changeId, "could not parse %s", fieldName);
    }
    return o;
  }

  private static int checkResult(int i, String fieldName, Change.Id changeId)
      throws ConfigInvalidException {
    if (i <= 0) {
      throw parseException(changeId, "could not parse %s", fieldName);
    }
    return i;
  }

  private PersonIdent newIdent(Account author, Date when) {
    return new PersonIdent(
        new AccountInfo(author).getName(anonymousCowardName),
        author.getId().get() + "@" + GERRIT_PLACEHOLDER_HOST,
        when, serverIdent.getTimeZone());
  }

  private static Account.Id parseIdent(PersonIdent ident, Change.Id changeId)
      throws ConfigInvalidException {
    String email = ident.getEmailAddress();
    int at = email.indexOf('@');
    if (at >= 0) {
      String host = email.substring(at + 1, email.length());
      Integer id = Ints.tryParse(email.substring(0, at));
      if (id != null && host.equals(GERRIT_PLACEHOLDER_HOST)) {
        return new Account.Id(id);
      }
    }
    throw parseException(changeId, "invalid identity, expected <id>@%s: %s",
      GERRIT_PLACEHOLDER_HOST, email);
  }

  private void appendHeaderField(PrintWriter writer,
      String field, String value) {
    writer.print(field);
    writer.print(": ");
    writer.print(value);
    writer.print('\n');
  }

  private static void checkHeaderLineFormat(byte[] note, MutableInteger curr,
      String fieldName, Charset enc, Change.Id changeId)
      throws ConfigInvalidException {
    boolean correct =
        RawParseUtils.match(note, curr.value, fieldName.getBytes(enc)) != -1;
    correct &= (note[curr.value + fieldName.length()] == ':');
    correct &= (note[curr.value + fieldName.length() + 1] == ' ');
    if (!correct) {
      throw parseException(changeId, "could not parse %s", fieldName);
    }
  }

  private final AccountCache accountCache;
  private final PersonIdent serverIdent;
  private final String anonymousCowardName;

  @Inject
  public CommentsInNotesUtil(AccountCache accountCache,
      @GerritPersonIdent PersonIdent serverIdent,
      @AnonymousCowardName String anonymousCowardName) {
    this.accountCache = accountCache;
    this.serverIdent = serverIdent;
    this.anonymousCowardName = anonymousCowardName;
  }

  /**
   * Build a note that contains the metadata for and the contents of all of the
   * comments in the given list of comments.
   *
   * @param comments
   *            A list of the comments to be written to the returned note
   *            byte array.
   *            All of the comments in this list must have the same side and
   *            must share the same PatchSet.Id.
   *            This list must not be empty because we cannot build a note
   *            for no comments.
   * @return the note. Null if there are no comments in the list.
   */
  public byte[] buildNote(List<PatchLineComment> comments) {
    ByteArrayOutputStream buf = new ByteArrayOutputStream();
    OutputStreamWriter streamWriter = new OutputStreamWriter(buf, UTF_8);
    try (PrintWriter writer = new PrintWriter(streamWriter)) {
      PatchLineComment first = comments.get(0);

      short side = first.getSide();
      PatchSet.Id psId = PatchLineCommentsUtil.getCommentPsId(first);
      appendHeaderField(writer, side == 0
          ? BASE_PATCH_SET
          : PATCH_SET,
          Integer.toString(psId.get()));
      appendHeaderField(writer, REVISION, first.getRevId().get());

      String currentFilename = null;

      for (PatchLineComment c : comments) {
        PatchSet.Id currentPsId = PatchLineCommentsUtil.getCommentPsId(c);
        checkArgument(psId.equals(currentPsId),
            "All comments being added must all have the same PatchSet.Id. The"
            + "comment below does not have the same PatchSet.Id as the others "
            + "(%s).\n%s", psId.toString(), c.toString());
        checkArgument(side == c.getSide(),
            "All comments being added must all have the same side. The"
            + "comment below does not have the same side as the others "
            + "(%s).\n%s", side, c.toString());
        String commentFilename =
            QuotedString.GIT_PATH.quote(c.getKey().getParentKey().getFileName());

        if (!commentFilename.equals(currentFilename)) {
          currentFilename = commentFilename;
          writer.print("File: ");
          writer.print(commentFilename);
          writer.print("\n\n");
        }

        // The CommentRange field for a comment is allowed to be null.
        // If it is indeed null, then in the first line, we simply use the line
        // number field for a comment instead. If it isn't null, we write the
        // comment range itself.
        CommentRange range = c.getRange();
        if (range != null) {
          writer.print(range.getStartLine());
          writer.print(':');
          writer.print(range.getStartCharacter());
          writer.print('-');
          writer.print(range.getEndLine());
          writer.print(':');
          writer.print(range.getEndCharacter());
        } else {
          writer.print(c.getLine());
        }
        writer.print("\n");

        writer.print(formatTime(serverIdent, c.getWrittenOn()));
        writer.print("\n");

        PersonIdent ident =
            newIdent(accountCache.get(c.getAuthor()).getAccount(),
                c.getWrittenOn());
        String nameString = ident.getName() + " <" + ident.getEmailAddress()
            + ">";
        appendHeaderField(writer, AUTHOR, nameString);

        String parent = c.getParentUuid();
        if (parent != null) {
          appendHeaderField(writer, PARENT, parent);
        }

        appendHeaderField(writer, UUID, c.getKey().get());

        byte[] messageBytes = c.getMessage().getBytes(UTF_8);
        appendHeaderField(writer, LENGTH,
            Integer.toString(messageBytes.length));

        writer.print(c.getMessage());
        writer.print("\n\n");
      }
    }
    return buf.toByteArray();
  }

  /**
   * Write comments for multiple revisions to a note map.
   * <p>
   * Mutates the map in-place. only notes for SHA-1s found as keys in the map
   * are modified; all other notes are left untouched.
   *
   * @param noteMap note map to modify.
   * @param allComments map of revision to all comments for that revision;
   *     callers are responsible for reading the original comments and applying
   *     any changes. Differs from a multimap in that present-but-empty values
   *     are significant, and indicate the note for that SHA-1 should be
   *     deleted.
   * @param inserter object inserter for writing notes.
   * @throws IOException if an error occurred.
   */
  public void writeCommentsToNoteMap(NoteMap noteMap,
      Map<RevId, List<PatchLineComment>> allComments, ObjectInserter inserter)
      throws IOException {
    for (Map.Entry<RevId, List<PatchLineComment>> e : allComments.entrySet()) {
      List<PatchLineComment> comments = e.getValue();
      ObjectId commit = ObjectId.fromString(e.getKey().get());
      if (comments.isEmpty()) {
        noteMap.remove(commit);
        continue;
      }
      Collections.sort(comments, PLC_ORDER);
      // We allow comments for multiple commits to be written in the same
      // update, even though the rest of the metadata update is associated with
      // a single patch set.
      noteMap.set(commit, inserter.insert(OBJ_BLOB, buildNote(comments)));
    }
  }

  static void addCommentToMap(Map<RevId, List<PatchLineComment>> map,
      PatchLineComment c) {
    List<PatchLineComment> list = map.get(c.getRevId());
    if (list == null) {
      list = new ArrayList<>();
      map.put(c.getRevId(), list);
    }
    list.add(c);
  }

}
