// Copyright (C) 2009 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;

import com.google.common.base.Optional;
import com.google.common.base.Strings;
import com.google.common.collect.Ordering;
import com.google.gerrit.common.errors.EmailException;
import com.google.gerrit.extensions.api.changes.ReviewInput.NotifyHandling;
import com.google.gerrit.reviewdb.client.AccountProjectWatch.NotifyType;
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.PatchSet;
import com.google.gerrit.server.PatchLineCommentsUtil;
import com.google.gerrit.server.patch.PatchFile;
import com.google.gerrit.server.patch.PatchList;
import com.google.gerrit.server.patch.PatchListNotAvailableException;
import com.google.gwtorm.client.KeyUtil;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;

import org.eclipse.jgit.lib.Repository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/** Send comments, after the author of them hit used Publish Comments in the UI. */
public class CommentSender extends ReplyToChangeSender {
  private static final Logger log = LoggerFactory
      .getLogger(CommentSender.class);

  public static interface Factory {
    public CommentSender create(NotifyHandling notify, Change change);
  }

  private final NotifyHandling notify;
  private List<PatchLineComment> inlineComments = Collections.emptyList();
  private final PatchLineCommentsUtil plcUtil;

  @Inject
  public CommentSender(EmailArguments ea,
      @Assisted NotifyHandling notify,
      @Assisted Change c,
      PatchLineCommentsUtil plcUtil) {
    super(ea, c, "comment");
    this.notify = notify;
    this.plcUtil = plcUtil;
  }

  public void setPatchLineComments(final List<PatchLineComment> plc)
      throws OrmException {
    inlineComments = plc;

    Set<String> paths = new HashSet<>();
    for (PatchLineComment c : plc) {
      Patch.Key p = c.getKey().getParentKey();
      if (!Patch.COMMIT_MSG.equals(p.getFileName())) {
        paths.add(p.getFileName());
      }
    }
    changeData.setCurrentFilePaths(Ordering.natural().sortedCopy(paths));
  }

  @Override
  protected void init() throws EmailException {
    super.init();

    if (notify.compareTo(NotifyHandling.OWNER_REVIEWERS) >= 0) {
      ccAllApprovals();
    }
    if (notify.compareTo(NotifyHandling.ALL) >= 0) {
      bccStarredBy();
      includeWatchers(NotifyType.ALL_COMMENTS);
    }
  }

  @Override
  public void formatChange() throws EmailException {
    appendText(velocifyFile("Comment.vm"));
  }

  @Override
  public void formatFooter() throws EmailException {
    appendText(velocifyFile("CommentFooter.vm"));
  }

  public boolean hasInlineComments() {
    return !inlineComments.isEmpty();
  }

  public String getInlineComments() {
    return getInlineComments(1);
  }

  public String getInlineComments(int lines) {
    StringBuilder cmts = new StringBuilder();
    final Repository repo = getRepository();
    try {
      PatchList patchList = null;
      if (repo != null) {
        try {
          patchList = getPatchList();
        } catch (PatchListNotAvailableException e) {
          log.error("Failed to get patch list", e);
        }
      }

      Patch.Key currentFileKey = null;
      PatchFile currentFileData = null;
      for (final PatchLineComment c : inlineComments) {
        final Patch.Key pk = c.getKey().getParentKey();

        if (!pk.equals(currentFileKey)) {
          String link = makeLink(pk);
          if (link != null) {
            cmts.append(link).append('\n');
          }
          if (Patch.COMMIT_MSG.equals(pk.get())) {
            cmts.append("Commit Message:\n\n");
          } else {
            cmts.append("File ").append(pk.get()).append(":\n\n");
          }
          currentFileKey = pk;

          if (patchList != null) {
            try {
              currentFileData =
                  new PatchFile(repo, patchList, pk.get());
            } catch (IOException e) {
              log.warn(String.format(
                  "Cannot load %s from %s in %s",
                  pk.getFileName(),
                  patchList.getNewId().name(),
                  projectState.getProject().getName()), e);
              currentFileData = null;
            }
          }
        }

        if (currentFileData != null) {
          appendComment(cmts, lines, currentFileData, c);
        }
        cmts.append("\n\n");
      }
    } finally {
      if (repo != null) {
        repo.close();
      }
    }
    return cmts.toString();
  }

  private void appendComment(StringBuilder out, int contextLines,
      PatchFile currentFileData, PatchLineComment comment) {
    short side = comment.getSide();
    CommentRange range = comment.getRange();
    if (range != null) {
      String prefix = String.format("Line %d: ", range.getStartLine());
      for (int n = range.getStartLine(); n <= range.getEndLine(); n++) {
        out.append(n == range.getStartLine()
            ? prefix
            : Strings.padStart(": ", prefix.length(), ' '));
        try {
          String s = currentFileData.getLine(side, n);
          if (n == range.getStartLine() && n == range.getEndLine()) {
            s = s.substring(
                Math.min(range.getStartCharacter(), s.length()),
                Math.min(range.getEndCharacter(), s.length()));
          } else if (n == range.getStartLine()) {
            s = s.substring(Math.min(range.getStartCharacter(), s.length()));
          } else if (n == range.getEndLine()) {
            s = s.substring(0, Math.min(range.getEndCharacter(), s.length()));
          }
          out.append(s);
        } catch (Throwable e) {
          // Don't quote the line if we can't safely convert it.
        }
        out.append('\n');
      }
      appendQuotedParent(out, comment);
      out.append(comment.getMessage().trim()).append('\n');
    } else {
      int lineNbr = comment.getLine();
      int maxLines;
      try {
        maxLines = currentFileData.getLineCount(side);
      } catch (Throwable e) {
        maxLines = lineNbr;
      }

      final int startLine = Math.max(1, lineNbr - contextLines + 1);
      final int stopLine = Math.min(maxLines, lineNbr + contextLines);

      for (int line = startLine; line <= lineNbr; ++line) {
        appendFileLine(out, currentFileData, side, line);
      }
      appendQuotedParent(out, comment);
      out.append(comment.getMessage().trim()).append('\n');

      for (int line = lineNbr + 1; line < stopLine; ++line) {
        appendFileLine(out, currentFileData, side, line);
      }
    }
  }

  private void appendFileLine(StringBuilder cmts, PatchFile fileData, short side, int line) {
    cmts.append("Line " + line);
    try {
      final String lineStr = fileData.getLine(side, line);
      cmts.append(": ");
      cmts.append(lineStr);
    } catch (Throwable e) {
      // Don't quote the line if we can't safely convert it.
    }
    cmts.append("\n");
  }

  private void appendQuotedParent(StringBuilder out, PatchLineComment child) {
    if (child.getParentUuid() != null) {
      Optional<PatchLineComment> parent;
      PatchLineComment.Key key = new PatchLineComment.Key(
          child.getKey().getParentKey(),
          child.getParentUuid());
      try {
        parent = plcUtil.get(args.db.get(), changeData.notes(), key);
      } catch (OrmException e) {
        log.warn("Could not find the parent of this comment: "
            + child.toString());
        parent = Optional.absent();
      }
      if (parent.isPresent()) {
        String msg = parent.get().getMessage().trim();
        if (msg.length() > 75) {
          msg = msg.substring(0, 75);
        }
        int lf = msg.indexOf('\n');
        if (lf > 0) {
          msg = msg.substring(0, lf);
        }
        out.append("> ").append(msg).append('\n');
      }
    }
  }

  // Makes a link back to the given patch set and file.
  private String makeLink(Patch.Key patch) {
    String url = getGerritUrl();
    if (url == null) {
      return null;
    }

    PatchSet.Id ps = patch.getParentKey();
    Change.Id c = ps.getParentKey();
    return new StringBuilder()
      .append(url)
      .append("#/c/").append(c)
      .append('/').append(ps.get())
      .append('/').append(KeyUtil.encode(patch.get()))
      .toString();
  }

  private Repository getRepository() {
    try {
      return args.server.openRepository(projectState.getProject().getNameKey());
    } catch (IOException e) {
      return null;
    }
  }
}
