package com.apobates.forum.trident.controller;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.apobates.forum.core.api.ImageIOMeta;
import com.apobates.forum.core.api.service.BoardGroupService;
import com.apobates.forum.core.api.service.BoardService;
import com.apobates.forum.core.api.service.TopicService;
import com.apobates.forum.core.entity.Board;
import com.apobates.forum.core.entity.BoardGroup;
import com.apobates.forum.core.entity.ForumEntityStatusEnum;
import com.apobates.forum.core.entity.Topic;
import com.apobates.forum.trident.exception.ResourceNotFoundException;
import com.apobates.forum.trident.spa.DocumentPage;
import com.apobates.forum.trident.spa.EntryItem;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
/**
 * 帮助中心控制器
 * 内置的help文件夹; 栏目,子栏目,文章
 * @author xiaofanku@live.cn
 * @since 20190927
 */
@Controller
@RequestMapping(value = "/article")
public class SectionArticleController {
	@Autowired
	private BoardGroupService boardGroupService;
	@Autowired
	private BoardService boardService;
	@Autowired
	private TopicService topicService;
	@Autowired
	private ImageIOMeta imageIOConfig;
	
	//各个模板都起作用的(栏目/子栏目)
	@GetMapping(path="/{section}/{term}/{id}.xhtml")
	public String getArticle(
			@PathVariable("section")String sectionDirectoryName,
			@PathVariable("term")String termDirectoryName,
			@PathVariable("id")long articleId, 
			HttpServletRequest request,
			Model model){
		Board term = boardService.getTermRelateSection(termDirectoryName);
		Topic article = topicService.getTermArticleContent(articleId, imageIOConfig);
		DocumentPage dp = DocumentPage.buildViewPage(article, term);
		model.addAttribute("page", dp);
		model.addAttribute("section", new EntryItem(term.getVolumes().getTitle(), String.format("/article/home?m=%s", term.getVolumes().getDirectoryNames())));
		return "default/"+sectionDirectoryName+"/"+termDirectoryName+"/view";
	}
	
	//单个内容页(只用到了栏目的模板)
	@GetMapping(path="/page")
	public String pageView(
			@RequestParam("bd")String termDirectoryName, //?
			@RequestParam(value = "id", required = false, defaultValue = "0")long articleId, 
			HttpServletRequest request,
			Model model){
		Board term = boardService.getTermRelateSection(termDirectoryName);
		if(null==term){
			throw new ResourceNotFoundException("目标对象不存在");
		}
		//
		Topic article = null;
		if(articleId>0){
			article = topicService.getTermArticleContent(articleId, imageIOConfig);
		}else{
			article = topicService.getFirstArticleForTerm(term.getId(), imageIOConfig); //子栏目的第一篇文章
		}
		
		if (null==article) {
			throw new ResourceNotFoundException("内容不存在或暂时无法访问");
		}
		DocumentPage dp = DocumentPage.buildViewPage(article, term);
		model.addAttribute("page", dp);
		model.addAttribute("section", new EntryItem(term.getVolumes().getTitle(), String.format("/article/home?m=%s", term.getVolumes().getDirectoryNames())));
		return "default/"+term.getVolumes().getDirectoryNames()+"/view"; 
	}
	
	//modelName的开始页
	@GetMapping(path="/home")
	public String homeView(
			@RequestParam("m")String sectionDirectoryName, //?
			HttpServletRequest request, 
			Model model){
		BoardGroup sectionObj = boardGroupService.getOriginByDirectoryNames(sectionDirectoryName).orElseThrow(()->new ResourceNotFoundException("目标对象不存在"));
		List<Board> terms = boardService.getAllTermByOriginId(sectionObj.getId());
		//
		model.addAttribute("page", DocumentPage.buildHomePage(sectionObj, terms));
		return "default/"+sectionDirectoryName+"/index"; 
	}
	
	//右侧的导航{版块名:xxx, 话题:[{},{}]}
	@GetMapping(path="/menu", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public String getPageMenu(
			@RequestParam("bd")String termDirectoryName, //?
			@RequestParam("id")long articleId, 
			HttpServletRequest request, 
			Model model){
		Optional<Board> term = boardService.getTermByDirectoryNames(termDirectoryName);
		if(!term.isPresent()){
			return "{}";
		}
		Board termObj = term.get();
		//
		EntryItem key = new EntryItem(termObj.getTitle(), String.format("/article/page?bd=%s", termDirectoryName));
		//
		Comparator<EntryItem> byTimestamp = Comparator.comparing(EntryItem::getLink);
		Supplier<TreeSet<EntryItem>> supplier = () -> new TreeSet<EntryItem>(byTimestamp);
		Set<EntryItem> entries =  topicService.getAllByBoard(termObj.getId(), ForumEntityStatusEnum.ACTIVE)
				.map(t -> new EntryItem(t.getTitle(), String.format("/article/page?bd=%s&id=%d", termDirectoryName, t.getId())))
				.collect(Collectors.toCollection(supplier));
		//
		Type setType = new TypeToken<TreeSet<EntryItem>>() {}.getType();
		Gson gson = new GsonBuilder().disableHtmlEscaping().create(); //Unicode转义字符(= / \u003d)
		JsonObject jsonObject = new JsonObject();
		jsonObject.addProperty("parent", gson.toJson(key));
		jsonObject.add("menu", gson.toJsonTree(entries, setType));
		return jsonObject.toString();
	}
	
	//指定文章的上一条|下一条
	@GetMapping(path="/navigate", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public Map<String,EntryItem> getPageNavigator(
			@RequestParam("bd")String termDirectoryName, //?
			@RequestParam("id")long articleId, 
			HttpServletRequest request, 
			Model model){
		Optional<Board> term = boardService.getTermByDirectoryNames(termDirectoryName);
		if (!term.isPresent()) {
			return Collections.emptyMap();
		}
		Map<String, Topic> data = topicService.getPrevNextTermArticle(term.get().getId(), articleId);
		Function<Entry<String, Topic>, String> keyMapper = entry -> entry.getKey().toLowerCase();
		Function<Entry<String, Topic>, EntryItem> valueMapper = entry -> new EntryItem(entry.getValue().getTitle(),String.format("/article/page?bd=%s&id=%d", termDirectoryName, entry.getValue().getId()));
		return data.entrySet().stream().collect(Collectors.toMap(keyMapper, valueMapper));
	}
}
