package org.ambraproject.wombat.controller;

import com.google.common.collect.ImmutableMap;
import org.ambraproject.wombat.config.site.RequestMappingContextDictionary;
import org.ambraproject.wombat.config.site.Site;
import org.ambraproject.wombat.config.site.SiteParam;
import org.ambraproject.wombat.config.site.url.Link;
import org.ambraproject.wombat.model.ScholarlyWorkId;
import org.ambraproject.wombat.service.ApiAddress;
import org.ambraproject.wombat.service.remote.ArticleApi;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Map;
import java.util.Objects;

@Controller
public class ScholarlyWorkController {

  @Autowired
  private ArticleApi articleApi;
  @Autowired
  private RequestMappingContextDictionary requestMappingContextDictionary;

  @RequestMapping(name = "work", value = "/work")
  public String renderWork(HttpServletRequest request,
                           Model model,
                           @SiteParam Site site,
                           ScholarlyWorkId workId)
      throws IOException {
    return getRedirectFor(getTypeOf(workId)).get(Link.toLocalSite(site), workId).getRedirect(request);
  }

  private String getTypeOf(ScholarlyWorkId workId) throws IOException {
    Map<String, Object> workMetadata = articleApi.requestObject(workId.appendId(ApiAddress.builder("work")), Map.class);
    return (String) workMetadata.get("type");
  }

  @FunctionalInterface
  private static interface TypeRedirect {
    Link get(Link.Factory factory, ScholarlyWorkId workId);
  }

  private Link redirectFigure(Link.Factory factory, ScholarlyWorkId workId) {
    return factory.toPattern(requestMappingContextDictionary, "article/figure")
        .addQueryParameter("id", workId.getDoi())
        .build();
  }

  private final ImmutableMap<String, TypeRedirect> REDIRECTS = ImmutableMap.<String, TypeRedirect>builder()
      .put("article", (factory, workId) ->
          factory.toPattern(requestMappingContextDictionary, "article")
              .addQueryParameter("id", workId.getDoi())
              .build())
      .put("figure", this::redirectFigure)
      .put("table", this::redirectFigure)
      // TODO: supp info
      .build();

  private TypeRedirect getRedirectFor(String type) {
    TypeRedirect redirect = REDIRECTS.get(Objects.requireNonNull(type));
    if (redirect == null) {
      throw new RuntimeException("Unrecognized type: " + type);
    }
    return redirect;
  }

}

@@ -597,45 +597,8 @@
 er;%0A
-import org.springframework.ui.Model;%0A
 impo
@@ -756,34 +756,8 @@
 Map;
-%0Aimport java.util.Objects;
 %0A%0A@C
@@ -1013,12 +1013,16 @@
 g re
-nder
+directTo
 Work
@@ -1060,42 +1060,8 @@
     
-                     Model model,%0A
     
@@ -1081,18 +1081,16 @@
         
-  
 @SitePar
@@ -1103,16 +1103,20 @@
 e site,%0A
+    
         
@@ -1215,53 +1215,12 @@
 For(
-getTypeOf(workId)).get(Link.toLocalSite(
 site
-)
 , wo
@@ -1228,24 +1228,16 @@
 kId).get
-Redirect
 (request
@@ -1494,376 +1494,22 @@
 %0A%0A  
-@FunctionalInterface%0A  private static interface TypeRedirect %7B%0A    Link get(Link.Factory factory, ScholarlyWorkId workId);%0A  %7D%0A%0A  private Link redirectFigure(Link.Factory factory, ScholarlyWorkId workId) %7B%0A    return factory.toPattern(requestMappingContextDictionary, %22article/figure%22)%0A        .addQueryParameter(%22id%22, workId.getDoi())%0A        .build();%0A  %7D%0A%0A  
 private
+ static
  fin
@@ -1532,28 +1532,22 @@
 String, 
-TypeRedirect
+String
 %3E REDIRE
@@ -1548,16 +1548,24 @@
 REDIRECT
+_HANDLER
 S = Immu
@@ -1582,28 +1582,22 @@
 String, 
-TypeRedirect
+String
 %3Ebuilder
@@ -1625,179 +1625,17 @@
 e%22, 
-(factory, workId) -%3E%0A          factory.toPattern(requestMappingContextDictionary, %22article%22)%0A              .addQueryParameter(%22id%22, workId.getDoi())%0A              .build()
+%22article%22
 )%0A  
@@ -1653,36 +1653,28 @@
 igure%22, 
-this::redirectFigure
+%22figurePage%22
 )%0A      
@@ -1691,36 +1691,32 @@
 e%22, 
-this::redirectFigure)%0A
+%22figurePage%22)%0A  
       
+  
 // T
@@ -1757,28 +1757,20 @@
 private 
-TypeRedirect
+Link
  getRedi
@@ -1782,91 +1782,126 @@
 or(S
-tring type) %7B%0A    TypeRedirect redirect = REDIRECTS.get(Objects.requireNonNull(type
+ite site, ScholarlyWorkId workId) throws IOException %7B%0A    String handlerName = REDIRECT_HANDLERS.get(getTypeOf(workId
 ));%0A
@@ -1908,24 +1908,27 @@
     if (
-redirect
+handlerName
  == null
@@ -1992,40 +1992,499 @@
 %22 + 
-type);%0A    %7D%0A    return redirect
+workId);%0A    %7D%0A    Link.Factory.PatternBuilder handlerLink = Link.toLocalSite(site)%0A        .toPattern(requestMappingContextDictionary, handlerName);%0A    return pointLinkToWork(handlerLink, workId);%0A  %7D%0A%0A  private static Link pointLinkToWork(Link.Factory.PatternBuilder link, ScholarlyWorkId workId) %7B%0A    link.addQueryParameter(%22id%22, workId.getDoi());%0A    workId.getRevisionNumber().ifPresent(revisionNumber -%3E%0A        link.addQueryParameter(%22rev%22, revisionNumber));%0A    return link.build()
 ;%0A  

Simplify ScholarlyWorkController