// 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.mail.receive;

import com.google.common.base.Strings;
import com.google.common.collect.Iterators;
import com.google.common.collect.PeekingIterator;
import com.google.gerrit.reviewdb.client.Comment;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/** TextParser provides parsing functionality for plaintext email. */
public class TextParser {
  /**
   * Parses comments from plaintext email.
   *
   * @param email MailMessage as received from the email service.
   * @param comments Comments previously persisted on the change that caused the original
   *     notification email to be sent out. Ordering must be the same as in the outbound email
   * @param changeUrl Canonical change url that points to the change on this Gerrit instance.
   *     Example: https://go-review.googlesource.com/#/c/91570
   * @return List of MailComments parsed from the plaintext part of the email.
   */
  public static List<MailComment> parse(
      MailMessage email, Collection<Comment> comments, String changeUrl) {
    String body = email.textContent();
    // Replace CR-LF by \n
    body = body.replace("\r\n", "\n");

    List<MailComment> parsedComments = new ArrayList<>();

    // Some email clients (like GMail) use >> for enquoting text when there are
    // inline comments that the users typed. These will then be enquoted by a
    // single >. We sanitize this by unifying it into >. Inline comments typed
    // by the user will not be enquoted.
    //
    // Example:
    // Some comment
    // >> Quoted Text
    // >> Quoted Text
    // > A comment typed in the email directly
    String singleQuotePattern = "\n> ";
    String doubleQuotePattern = "\n>> ";
    if (countOccurrences(body, doubleQuotePattern) > countOccurrences(body, singleQuotePattern)) {
      body = body.replace(doubleQuotePattern, singleQuotePattern);
    }

    PeekingIterator<Comment> iter = Iterators.peekingIterator(comments.iterator());

    String[] lines = body.split("\n");
    MailComment currentComment = null;
    String lastEncounteredFileName = null;
    Comment lastEncounteredComment = null;
    for (String line : lines) {
      if (line.equals(">")) {
        // Skip empty lines
        continue;
      }
      if (line.startsWith("> ")) {
        line = line.substring("> ".length()).trim();
        // This is not a comment, try to advance the file/comment pointers and
        // add previous comment to list if applicable
        if (currentComment != null) {
          if (currentComment.type == MailComment.CommentType.CHANGE_MESSAGE) {
            currentComment.message = ParserUtil.trimQuotation(currentComment.message);
          }
          if (!Strings.isNullOrEmpty(currentComment.message)) {
            parsedComments.add(currentComment);
          }
          currentComment = null;
        }

        if (!iter.hasNext()) {
          continue;
        }
        Comment perspectiveComment = iter.peek();
        if (line.equals(ParserUtil.filePath(changeUrl, perspectiveComment))) {
          if (lastEncounteredFileName == null
              || !lastEncounteredFileName.equals(perspectiveComment.key.filename)) {
            // This is the annotation of a file
            lastEncounteredFileName = perspectiveComment.key.filename;
            lastEncounteredComment = null;
          } else if (perspectiveComment.lineNbr == 0) {
            // This was originally a file-level comment
            lastEncounteredComment = perspectiveComment;
            iter.next();
          }
        } else if (ParserUtil.isCommentUrl(line, changeUrl, perspectiveComment)) {
          lastEncounteredComment = perspectiveComment;
          iter.next();
        }
      } else {
        // This is a comment. Try to append to previous comment if applicable or
        // create a new comment.
        if (currentComment == null) {
          // Start new comment
          currentComment = new MailComment();
          currentComment.message = line;
          if (lastEncounteredComment == null) {
            if (lastEncounteredFileName == null) {
              // Change message
              currentComment.type = MailComment.CommentType.CHANGE_MESSAGE;
            } else {
              // File comment not sent in reply to another comment
              currentComment.type = MailComment.CommentType.FILE_COMMENT;
              currentComment.fileName = lastEncounteredFileName;
            }
          } else {
            // Comment sent in reply to another comment
            currentComment.inReplyTo = lastEncounteredComment;
            currentComment.type = MailComment.CommentType.INLINE_COMMENT;
          }
        } else {
          // Attach to previous comment
          currentComment.message += "\n" + line;
        }
      }
    }
    // There is no need to attach the currentComment after this loop as all
    // emails have footers and other enquoted text after the last comment
    // appeared and the last comment will have already been added to the list
    // at this point.

    return parsedComments;
  }

  /** Counts the occurrences of pattern in s */
  private static int countOccurrences(String s, String pattern) {
    return (s.length() - s.replace(pattern, "").length()) / pattern.length();
  }
}
