/*
 * $HeadURL$
 * $Id$
 * Copyright (c) 2006-2013 by Public Library of Science http://plos.org http://ambraproject.org
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.ambraproject.rhino.rest.controller;

import com.google.common.base.Strings;
import org.ambraproject.models.Article;
import org.ambraproject.models.Category;
import org.ambraproject.rhino.identity.ArticleIdentity;
import org.ambraproject.rhino.rest.controller.abstr.RestController;
import org.ambraproject.rhino.service.ArticleCrudService;
import org.ambraproject.rhino.service.ClassificationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;

/**
 * Controller class for the taxonomy namespace.
 */
@Controller
public class TaxonomyController extends RestController {

  private static final String TAXONOMY_ROOT = "/taxonomy";
  private static final String TAXONOMY_NAMESPACE = TAXONOMY_ROOT + '/';
  private static final String TAXONOMY_TEMPLATE = TAXONOMY_NAMESPACE + "**";

  @Autowired
  private ClassificationService classificationService;

  @Autowired
  protected ArticleCrudService articleCrudService;

  @Transactional(readOnly = true)
  @RequestMapping(value = TAXONOMY_TEMPLATE, method = RequestMethod.GET)
  public void readRoot(HttpServletRequest request, HttpServletResponse response,
                       @RequestParam(value = "journal", required = true) String journal)
      throws Exception {
    String parent = getFullPathVariable(request, true, TAXONOMY_NAMESPACE);
    if (!Strings.isNullOrEmpty(parent)) {
      parent = URLDecoder.decode(parent, "UTF-8");
    }
    classificationService.read(journal, parent).respond(request, response, entityGson);
  }


  @RequestMapping(value = TAXONOMY_NAMESPACE + "flag/{action:add|remove}", method = RequestMethod.POST)
  public @ResponseBody Map<String,String> flagArticleCategory(HttpServletRequest request, HttpServletResponse response,
                       @RequestParam(value = "categoryTerm", required = true) String categoryTerm,
                       @RequestParam(value = "articleDoi", required = true) String articleDoi,
                       @RequestParam(value = "authId", required = true) String authId,
                       @PathVariable("action") String action)
          throws Exception {
    // TODO: we might want to optimize this by directly retrieving an article category collection in place of article instantiation
    Article article = articleCrudService.findArticleById(ArticleIdentity.create(articleDoi));
    for (Category category : article.getCategories().keySet()) {
      // if category matches the provided term, insert or delete an article category flag according to action provided in url
      // NOTE: a given category term (i.e. the final term in a full category path) may be present for more than one article category
      String[] terms = category.getPath().split("/");
      String articleCategoryTerm = terms[terms.length - 1];
      if (categoryTerm.contentEquals(articleCategoryTerm)) {
        if (action.contentEquals("remove")) {
          classificationService.deflagArticleCategory(article.getID(), category.getID(), authId);
        } else if (action.contentEquals("add")) {
          classificationService.flagArticleCategory(article.getID(), category.getID(), authId);
        }
      }
    }

    Map testMap = new HashMap<String,String>();
    return testMap;
  }

  @Transactional(readOnly = false)
  @RequestMapping(value = TAXONOMY_NAMESPACE + "flag", method = RequestMethod.DELETE)
  public @ResponseBody void deflagArticleCategory(HttpServletRequest request, HttpServletResponse response,
                                  @RequestParam(value = "categoryId", required = false) Long categoryId,
                                  @RequestParam(value = "articleId", required = false) Long articleId,
                                  @RequestParam(value = "authId", required = false) String authId)
          throws Exception {
    //classificationService.deflagArticleCategory(articleId, categoryId, authId);
    response.setStatus(HttpStatus.CREATED.value());
    Map testMap = new HashMap<String,String>();
    return;
  }
}

@@ -2593,16 +2593,65 @@
 );%0A  %7D%0A%0A
+  @Transactional(rollbackFor = %7BThrowable.class%7D)
 %0A  @Requ
@@ -4282,843 +4282,111 @@
   %7D%0A
-%0A
     
-Map testMap = new HashMap%3CString,String%3E();%0A    return testMap;%0A  %7D%0A%0A  @Transactional(readOnly = false)%0A  @RequestMapping(value = TAXONOMY_NAMESPACE + %22flag%22, method = RequestMethod.DELETE)%0A  public @ResponseBody void deflagArticleCategory(HttpServletRequest request, HttpServletResponse response,%0A                                  @RequestParam(value = %22categoryId%22, required = false) Long categoryId,%0A                                  @RequestParam(value = %22articleId%22, required = false) Long articleId,%0A                                  @RequestParam(value = %22authId%22, required = false) String authId)%0A          throws Exception %7B%0A    //classificationService.deflagArticleCategory(articleId, categoryId, authId);%0A    response.setStatus(HttpStatus.CREATED.value());%0A    Map testMap = new HashMap%3CString,String%3E();%0A    return;
+return new HashMap%3C%3E(); // ajax call expects returned data so provide an empty map for the body
 %0A  %7D%0A
+%0A
 %7D%0A

clean up for TaxonomyController