package org.ambraproject.wombat.feed;

import com.google.common.collect.ImmutableList;
import com.rometools.rome.feed.atom.Category;
import com.rometools.rome.feed.atom.Entry;
import com.rometools.rome.feed.atom.Link;
import com.rometools.rome.feed.rss.Guid;
import com.rometools.rome.feed.rss.Item;
import org.ambraproject.wombat.config.site.RequestMappingContextDictionary;
import org.ambraproject.wombat.service.CommentFormatting;
import org.springframework.beans.factory.annotation.Autowired;

import java.time.Instant;
import java.util.Date;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

public class CommentFeedView extends AbstractFeedView<Map<String, Object>> {

  @Autowired
  private RequestMappingContextDictionary requestMappingContextDictionary;

  private String getCommentUrl(FeedMetadata feedMetadata, String commentId) {
    return feedMetadata.buildLink(link -> link
        .toPattern(requestMappingContextDictionary, "articleComments")
        .addQueryParameter("id", commentId)
        .build());
  }

  private String getArticleUrl(FeedMetadata feedMetadata, Map<String, Object> article) {
    return feedMetadata.buildLink(link -> link
        .toPattern(requestMappingContextDictionary, "article")
        .addQueryParameter("id", article.get("doi"))
        .build());
  }

  private static String getCreatorDisplayName(Map<String, Object> comment) {
    Map<String, Object> creator = (Map<String, Object>) comment.get("creator");
    return (String) creator.get("displayName");
  }

  private static Date getCommentDate(Map<String, Object> comment) {
    return Date.from(Instant.parse((String) comment.get("lastModified")));
  }

  private String createCommentHtml(FeedMetadata feedMetadata, Map<String, Object> comment) {
    Map<String, Object> article = (Map<String, Object>) comment.get("parentArticle");
    String articleTitle = (String) Objects.requireNonNull(article.get("title"));

    String header = String.format("<p>Comment on <a href=\"%s\">%s</a></p>\n",
        getArticleUrl(feedMetadata, article), articleTitle);

    CommentFormatting.FormattedComment formatted = new CommentFormatting.FormattedComment(comment);
    return header + formatted.getBodyWithHighlightedText();
  }

  @Override
  protected Item createRssItem(FeedMetadata feedMetadata, Map<String, Object> comment) {
    String commentId = (String) comment.get("annotationUri");

    Item item = new Item();
    item.setTitle((String) comment.get("title"));
    item.setLink(getCommentUrl(feedMetadata, commentId));
    item.setAuthor(getCreatorDisplayName(comment));
    item.setPubDate(getCommentDate(comment));

    Guid guid = new Guid();
    guid.setValue(commentId);
    guid.setPermaLink(false);
    item.setGuid(guid);

    com.rometools.rome.feed.rss.Content content = new com.rometools.rome.feed.rss.Content();
    content.setType(com.rometools.rome.feed.rss.Content.HTML);
    content.setValue(createCommentHtml(feedMetadata, comment));
    item.setContent(content);

    return item;
  }

  @Override
  protected Entry createAtomEntry(FeedMetadata feedMetadata, Map<String, Object> comment) {
    Map<String, Object> article = (Map<String, Object>) comment.get("parentArticle");
    String commentId = (String) comment.get("annotationUri");
    String commentTitle = (String) comment.get("title");

    Entry entry = new Entry();
    entry.setId(commentId);
    entry.setTitle(commentTitle);
    entry.setAuthors(ImmutableList.of(createAtomPerson(getCreatorDisplayName(comment))));
    createAtomCategory(comment).map(ImmutableList::of).ifPresent(entry::setCategories);

    Link commentLink = createAtomLink(getCommentUrl(feedMetadata, commentId),
        commentTitle, Optional.empty(), Optional.empty());
    Link articleLink = createAtomLink(getArticleUrl(feedMetadata, article),
        (String) article.get("title"), Optional.of("related"), Optional.empty());
    entry.setAlternateLinks(ImmutableList.of(commentLink, articleLink));

    Date lastModified = getCommentDate(comment);
    entry.setPublished(lastModified);
    entry.setUpdated(lastModified);

    com.rometools.rome.feed.atom.Content content = new com.rometools.rome.feed.atom.Content();
    content.setType(com.rometools.rome.feed.atom.Content.HTML);
    content.setValue(createCommentHtml(feedMetadata, comment));
    entry.setContents(ImmutableList.of(content));

    return entry;
  }

  private static Optional<Category> createAtomCategory(Map<String, Object> comment) {
    String type = (String) comment.get("type");
    if (type == null) return Optional.empty();
    Category category = new Category();
    category.setTerm(type);
    category.setLabel(type);
    return Optional.of(category);
  }

}

@@ -28,24 +28,63 @@
 mbat.feed;%0A%0A
+import com.google.common.base.Strings;%0A
 import com.g
@@ -119,16 +119,16 @@
 leList;%0A
-
 import c
@@ -653,16 +653,84 @@
 ptional;
+%0Aimport java.util.stream.Collectors;%0Aimport java.util.stream.Stream;
 %0A%0Apublic
@@ -1780,32 +1780,477 @@
 ified%22)));%0A  %7D%0A%0A
+  private static String formatUserName(Map%3CString, Object%3E userProfile) %7B%0A    String givenNames = Strings.emptyToNull((String) userProfile.get(%22givenNames%22));%0A    String surname = Strings.emptyToNull((String) userProfile.get(%22surname%22));%0A%0A    return (givenNames == null && surname == null)%0A        ? (String) userProfile.get(%22displayName%22)%0A        : Stream.of(givenNames, surname).filter(Objects::nonNull).collect(Collectors.joining(%22 %22));%0A  %7D%0A%0A
   private String
@@ -2631,24 +2631,225 @@
 cleTitle);%0A%0A
+    String author = formatUserName((Map%3CString, Object%3E) comment.get(%22creator%22));%0A    String authorAttribution = Strings.isNullOrEmpty(author) ? %22%22%0A        : String.format(%22%3Cp%3EBy %25s:%3C/p%3E%5Cn%22, author);%0A%0A
     CommentF
@@ -2932,24 +2932,24 @@
 t(comment);%0A
-
     return h
@@ -2955,16 +2955,36 @@
 header +
+ authorAttribution +
  formatt

Add author attribution to comment feed content