package org.ambraproject.rhino.view.article.versioned;

import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.ambraproject.rhino.model.ArticleFile;
import org.ambraproject.rhino.model.ArticleIngestion;
import org.ambraproject.rhino.model.ArticleItem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateTemplate;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

public class ItemSetView {

  public static class Factory {
    @Autowired
    private HibernateTemplate hibernateTemplate;

    public ItemSetView getView(ArticleIngestion ingestion) {
      Collection<ArticleItem> items = (List<ArticleItem>) hibernateTemplate.find("FROM ArticleItem WHERE ingestion = ?", ingestion);
      Collection<ArticleFile> files = (List<ArticleFile>) hibernateTemplate.find("FROM ArticleFile WHERE ingestion = ?", ingestion);
      return new ItemSetView(items, files);
    }
  }

  private final ImmutableMap<String, ItemView> items;
  private final ImmutableCollection<FileView> archival;

  private ItemSetView(Collection<ArticleItem> items, Collection<ArticleFile> files) {
    Map<ArticleItem, List<ArticleFile>> itemFileGroups = files.stream()
        .filter(file -> file.getItem() != null)
        .collect(Collectors.groupingBy(ArticleFile::getItem));
    if (!items.containsAll(itemFileGroups.keySet())) {
      throw new RuntimeException("Data integrity violation: files and items have inconsistent ingestions");
    }
    this.items = ImmutableMap.copyOf(itemFileGroups.entrySet().stream()
        .collect(Collectors.toMap(
            entry -> entry.getKey().getDoi(),
            entry -> new ItemView(entry.getKey(), entry.getValue()))));

    this.archival = ImmutableList.copyOf(files.stream()
        .filter(file -> file.getItem() == null)
        .map(FileView::new)
        .collect(Collectors.toList()));
  }

  private static class ItemView {
    private final String itemType;
    private final ImmutableMap<String, FileView> files;

    private ItemView(ArticleItem item, Collection<ArticleFile> files) {
      this.itemType = Objects.requireNonNull(item.getItemType());
      this.files = ImmutableMap.copyOf(files.stream()
          .collect(Collectors.toMap(ArticleFile::getFileType, FileView::new)));
    }
  }

  private static class FileView {
    private final String bucketName;
    private final String crepoKey;
    private final String crepoUuid;

    private FileView(ArticleFile file) {
      this.bucketName = Objects.requireNonNull(file.getBucketName());
      this.crepoKey = Objects.requireNonNull(file.getCrepoKey());
      this.crepoUuid = Objects.requireNonNull(file.getCrepoUuid());
    }
  }

}

@@ -802,141 +802,8 @@
 ) %7B%0A
-      Collection%3CArticleItem%3E items = (List%3CArticleItem%3E) hibernateTemplate.find(%22FROM ArticleItem WHERE ingestion = ?%22, ingestion);%0A
     
@@ -961,20 +961,24 @@
 etView(i
-tems
+ngestion
 , files)
@@ -1127,37 +1127,34 @@
 iew(
-Collection%3CArticleItem%3E items
+ArticleIngestion ingestion
 , Co
@@ -1375,172 +1375,66 @@
     
-if (!items.containsAll(itemFileGroups.keySet())) %7B%0A      throw new RuntimeException(%22Data integrity violation: files and items have inconsistent ingestions%22);%0A    %7D
+validateItemParentage(ingestion, itemFileGroups.keySet());
 %0A   
@@ -1788,16 +1788,16 @@
 w::new)%0A
-
         
@@ -1829,24 +1829,739 @@
 t()));%0A  %7D%0A%0A
+  /**%0A   * Validate that all items (belonging to a set of files) have the expected parent ingestion.%0A   */%0A  private static void validateItemParentage(ArticleIngestion ingestion, Collection%3CArticleItem%3E items) %7B%0A    for (ArticleItem item : items) %7B%0A      ArticleIngestion itemIngestion = item.getIngestion();%0A      if (!itemIngestion.equals(ingestion)) %7B%0A        String message = String.format(%22Data integrity violation: item %25s has ingestion (%25s, %25d); expected (%25s, %25d)%22, item.getDoi(),%0A            itemIngestion.getArticle().getDoi(), itemIngestion.getIngestionNumber(),%0A            ingestion.getArticle().getDoi(), ingestion.getIngestionNumber());%0A        throw new RuntimeException(message);%0A      %7D%0A    %7D%0A  %7D%0A%0A
   private st

Clarify data integrity check on ArticleFile's parent items