package org.ambraproject.wombat.feed;

import com.google.common.base.Strings;
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.plos.ned_client.model.Individualprofile;
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;
import java.util.stream.Collectors;
import java.util.stream.Stream;

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 Date getCommentDate(Map<String, Object> comment) {
    return Date.from(Instant.parse((String) comment.get("lastModified")));
  }

  private static String formatUserName(Individualprofile userProfile) {
    String givenNames = Strings.emptyToNull((userProfile.getFirstname()));
    String surname = Strings.emptyToNull((String) userProfile.getLastname());

    return (givenNames == null && surname == null)
        ? (String) userProfile.getDisplayname()
        : Stream.of(givenNames, surname).filter(Objects::nonNull).collect(Collectors.joining(" "));
  }

  private String createCommentHtml(FeedMetadata feedMetadata, Map<String, Object> comment) {
    Individualprofile profile = getCreatorProfile(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);

    String author = formatUserName(profile);
    String authorAttribution = Strings.isNullOrEmpty(author) ? ""
        : String.format("<p>By %s:</p>\n", author);

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

  private static Individualprofile getCreatorProfile(Map<String, Object> comment) {
    return (Individualprofile) comment.get("creator");
  }

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

    Individualprofile profile = getCreatorProfile(comment);

    Item item = new Item();
    item.setTitle((String) comment.get("title"));
    item.setLink(getCommentUrl(feedMetadata, commentId));
    item.setAuthor(profile.getDisplayname());
    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");

    Individualprofile profile = getCreatorProfile(comment);

    Entry entry = new Entry();
    entry.setId(commentId);
    entry.setTitle(commentTitle);
    entry.setAuthors(ImmutableList.of(createAtomPerson(profile.getDisplayname())));
    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);
  }

}

@@ -1474,32 +1474,227 @@
 .build());%0A  %7D%0A%0A
+  private static String getCreatorDisplayName(Map%3CString, Object%3E comment) %7B%0A    Individualprofile creator = (Individualprofile) comment.get(%22creator%22);%0A    return creator.getDisplayname();%0A  %7D%0A%0A
   private static
@@ -1941,17 +1941,16 @@
 yToNull(
-(
 userProf
@@ -1968,17 +1968,16 @@
 tname())
-)
 ;%0A    St
@@ -2011,25 +2011,16 @@
 yToNull(
-(String) 
 userProf
@@ -2100,25 +2100,16 @@
        ?
- (String)
  userPro
@@ -2332,69 +2332,8 @@
 ) %7B%0A
-    Individualprofile profile = getCreatorProfile(comment);%0A%0A
     
@@ -2672,23 +2672,58 @@
 serName(
-profile
+(Individualprofile) comment.get(%22creator%22)
 );%0A    S
@@ -3025,152 +3025,8 @@
  %7D%0A%0A
-  private static Individualprofile getCreatorProfile(Map%3CString, Object%3E comment) %7B%0A    return (Individualprofile) comment.get(%22creator%22);%0A  %7D%0A%0A
   @O
@@ -3189,69 +3189,8 @@
 );%0A%0A
-    Individualprofile profile = getCreatorProfile(comment);%0A%0A
     
@@ -3340,39 +3340,45 @@
 tAuthor(
-profile.get
+getCreator
 Display
-n
+N
 ame(
+comment
 ));%0A    
@@ -4120,69 +4120,8 @@
 );%0A%0A
-    Individualprofile profile = getCreatorProfile(comment);%0A%0A
     
@@ -4268,31 +4268,37 @@
 son(
-profile.get
+getCreator
 Display
-n
+N
 ame(
+comment
 ))))

Clean up CommentFeedView