package org.ambraproject.rhino.view.asset.groomed;


import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Maps;
import com.google.gson.JsonObject;
import com.google.gson.JsonSerializationContext;
import org.ambraproject.models.ArticleAsset;
import org.ambraproject.rhino.view.JsonOutputView;

import java.util.Collection;
import java.util.Map;

public class GroomedFigureView implements JsonOutputView {

  private final ArticleAsset original;
  private final Map<FigureType, ArticleAsset> thumbnails;

  private GroomedFigureView(ArticleAsset original, Map<FigureType, ArticleAsset> thumbnails) {
    this.original = Preconditions.checkNotNull(original);
    this.thumbnails = ImmutableSortedMap.copyOf(thumbnails);
    Preconditions.checkArgument(!this.thumbnails.containsKey(FigureType.ORIGINAL));
  }

  public static GroomedFigureView create(Collection<ArticleAsset> figureAssets) {
    Map<FigureType, ArticleAsset> byType = Maps.newEnumMap(FigureType.class);
    for (ArticleAsset asset : figureAssets) {
      byType.put(FigureType.fromExtension(asset.getExtension()), asset);
    }

    ArticleAsset original = byType.remove(FigureType.ORIGINAL);
    if (original == null) {
      String message = "Original asset not found. Expected an asset with an extension: "
          + FigureType.ORIGINAL.getAssociatedExtensions();
      throw new IllegalArgumentException(message);
    }

    return new GroomedFigureView(original, byType);
  }

  @Override
  public JsonObject serialize(JsonSerializationContext context) {
    JsonObject serialized = new JsonObject();

    serialized.addProperty("doi", original.getDoi());
    serialized.addProperty("title", original.getTitle());
    serialized.addProperty("description", original.getDescription());

    serialized.add("original", context.serialize(new AssetFileView(original)));

    JsonObject serializedThumbnails = new JsonObject();
    for (Map.Entry<FigureType, ArticleAsset> entry : thumbnails.entrySet()) {
      String key = entry.getKey().name().toLowerCase();
      ArticleAsset thumbnail = entry.getValue();
      JsonObject serializedThumbnail = (JsonObject) context.serialize(new AssetFileView(thumbnail));

      // Exclude members already shown one level up
      JsonObject thumbnailMetadata = (JsonObject) serializedThumbnail.get("metadata");
      thumbnailMetadata.remove("title");
      thumbnailMetadata.remove("description");

      serializedThumbnails.add(key, serializedThumbnail);
    }
    serialized.add("thumbnails", serializedThumbnails);

    return serialized;
  }

}

@@ -1518,16 +1518,839 @@
 );%0A  %7D%0A%0A
+  /**%0A   * Fields that should be shown as a property of the entire figure and suppressed from the thumbnail metadata.%0A   */%0A  private static enum FigureMetadataField %7B%0A    TITLE(%22title%22) %7B%0A      @Override%0A      protected Object access(ArticleAsset asset) %7B%0A        return asset.getTitle();%0A      %7D%0A    %7D,%0A    DESCRIPTION(%22description%22) %7B%0A      @Override%0A      protected Object access(ArticleAsset asset) %7B%0A        return asset.getDescription();%0A      %7D%0A    %7D,%0A    CONTEXT_ELEMENT(%22contextElement%22) %7B%0A      @Override%0A      protected Object access(ArticleAsset asset) %7B%0A        return asset.getContextElement();%0A      %7D%0A    %7D;%0A%0A    private final String memberName;%0A%0A    private FigureMetadataField(String memberName) %7B%0A      this.memberName = memberName;%0A    %7D%0A%0A    protected abstract Object access(ArticleAsset asset);%0A  %7D%0A%0A
   @Overr
@@ -2465,17 +2465,16 @@
 ject();%0A
-%0A
     seri
@@ -2523,135 +2523,254 @@
 ));%0A
+%0A
     
-serialized.addProperty(%22title%22, original.getTitle());%0A    serialized.addProperty(%22description%22, original.getDescription());
+// Pull figure-level metadata values from the original (ignore those of thumbnails)%0A    for (FigureMetadataField field : FigureMetadataField.values()) %7B%0A      serialized.add(field.memberName, context.serialize(field.access(original)));%0A    %7D
 %0A%0A  
@@ -3338,43 +3338,75 @@
     
-thumbnailMetadata.remove(%22title%22);%0A
+for (FigureMetadataField field : FigureMetadataField.values()) %7B%0A  
     
@@ -3436,23 +3436,34 @@
 ove(
-%22description%22);
+field.memberName);%0A      %7D
 %0A%0A  

Add contextElement to figure-level metadata; generalize