package com.apobates.forum.trident.controller;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.Map.Entry;
import java.util.function.Function;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
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.AlbumPictureService;
import com.apobates.forum.core.api.service.AlbumService;
import com.apobates.forum.core.api.service.BoardGroupService;
import com.apobates.forum.core.api.service.BoardModeratorService;
import com.apobates.forum.core.api.service.BoardService;
import com.apobates.forum.core.api.service.BoardStatsService;
import com.apobates.forum.core.api.service.BoardTopicCategoryIndexService;
import com.apobates.forum.core.api.service.TopicService;
import com.apobates.forum.core.entity.Album;
import com.apobates.forum.core.entity.AlbumPicture;
import com.apobates.forum.core.entity.Board;
import com.apobates.forum.core.entity.BoardGroup;
import com.apobates.forum.core.entity.BoardStats;
import com.apobates.forum.core.entity.ForumEntityStatusEnum;
import com.apobates.forum.core.entity.Topic;
import com.apobates.forum.core.entity.TopicCategory;
import com.apobates.forum.event.elderly.ForumActionEnum;
import com.apobates.forum.trident.digest.ForumThreadsDigest;
import com.apobates.forum.trident.vo.ForumBoardStats;
import com.apobates.forum.trident.vo.ForumBoardStatsRecord;
import com.apobates.forum.trident.vo.ForumThreads;
import com.apobates.forum.trident.vo.ThreadsAlbumPicture;
import com.apobates.forum.utils.CommonBean;
import com.apobates.forum.utils.Commons;
import com.google.gson.Gson;
/**
 * 异步加载的控制器
 * 
 * @author xiaofanku
 * @since 20191201
 */
@Controller
@RequestMapping(value = "/loader")
public class LazyLoadController {
	@Autowired
	private BoardTopicCategoryIndexService boardTopicCategoryIndexService;
	@Autowired
	private BoardStatsService boardStatsService;
	@Autowired
	private BoardModeratorService boardModeratorService;
	@Autowired
	private AlbumService albumService;
	@Autowired
	private AlbumPictureService albumPictureService;
	@Autowired
	private BoardGroupService boardGroupService;
	@Autowired
	private BoardService boardService;
	@Autowired
	private TopicService topicService;
	@Autowired
	private ImageIOMeta imageIOConfig;
	@Value("${site.sensitive.dictionary}")
	private String sensitiveDictionary;
	
	// ----------------------------------------------------------------------版块组的
	// [发布主题]版块组(卷)列表[OK]
	// 可发贴的
	@GetMapping(path = "/volumes/usable.json", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public List<CommonBean> getAllBoardGroup(HttpServletRequest request, Model model) {
		List<CommonBean> data = boardGroupService.getAllUsed().stream().map(bg -> new CommonBean(bg.getId(), bg.getTitle())).collect(Collectors.toList());
		// 增补默认版块组(卷)
		BoardGroup defaultGroup = BoardGroup.getDefault();
		data.add(new CommonBean(defaultGroup.getId(), defaultGroup.getTitle()));
		return data;
	}

	// 版块组下的热门话题[OK]
	@GetMapping(path = "/volumes/topic/hot.json", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public List<ForumThreadsDigest> getHotTopic(@RequestParam("id") int boardGroupId, HttpServletRequest request, Model model) {
		return topicService.getMaxReplyForBoardGroup(boardGroupId, 10).map(ForumThreadsDigest::new).collect(Collectors.toList());
	}

	// 版块组下的精华话题[OK]
	@GetMapping(path = "/volumes/topic/best.json", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public List<ForumThreadsDigest> getBestTopic(@RequestParam("id") int boardGroupId, HttpServletRequest request, Model model) {
		return topicService.getGoodsForBoardGroup(boardGroupId, 10).map(ForumThreadsDigest::new).collect(Collectors.toList());
	}
	
	// 版块组下最近的话题[OK]
	@GetMapping(path = "/volumes/topic/recent.json", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public String getVolumesRecentTopic(
			@RequestParam("id") int boardGroupId, 
			@RequestParam(value = "size", required = false, defaultValue = "0") int showSize, 
			HttpServletRequest request, 
			Model model){
		int ss = (showSize == 0)?10:showSize;
		List<ForumThreads> data=topicService.getRecent(boardGroupId, ss).sorted(Comparator.comparing(Topic::getRankingDateTime).reversed()).map(ForumThreads::new).collect(Collectors.toList());
		Gson gson = new Gson();
		return gson.toJson(data);
	}

	// 大版块下所有在线的大版主
	@GetMapping(path = "/volumes/moderator.json", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public List<CommonBean> getBoardGroupModeratores(@RequestParam("id") int boardGroupId, HttpServletRequest request, Model model) {
		return boardModeratorService.getAllUsedByBoardGroupId(boardGroupId).map(bm -> new CommonBean(bm.getMemberId(), bm.getMemberNickname())).collect(Collectors.toList());
	}
	// 服务于版块导航[OK]
	// key=CommonBean(版块组ID, 版块组名称), value=版块组下的版块
	@GetMapping(path = "/board/select.jsonp", produces = "application/javascript;charset=UTF-8")
	@ResponseBody
	public String getAllBoardGroupAndBoard(@RequestParam("callback") String callBackFun,
			@RequestParam(value = "box", required = false, defaultValue = "null") String boxEle,
			HttpServletRequest request, Model model) {
		List<BoardGroup> rs = boardGroupService.getAllUsedAndBoard(false);
		if (rs.isEmpty()) {
			return callBackFun + "({});";
		}
		Function<BoardGroup, String> keyMapper = bg -> bg.getTitle();
		Function<BoardGroup, List<Map<String, String>>> valueMapper = bg -> {
			return bg.getBoardes().stream().map(b -> {
				String key = b.getId() + "-" + bg.getId();
				HashMap<String, String> tmp = new HashMap<>();
				tmp.put(key, b.getTitle());
				return tmp;
			}).collect(Collectors.toList());
		};
		Map<String, List<Map<String, String>>> data = rs.stream().collect(Collectors.toConcurrentMap(keyMapper, valueMapper));
		Map<String, Object> result = new HashMap<>();
		result.put("element", boxEle);
		result.put("result", data);
		return callBackFun + "(" + new Gson().toJson(result) + ");";
	}

	// 由于采用缓存.导致版块的统计显示错误[OK]
	// 版块列表[所有版块的统计]
	/* 版块组内容页[指定版块的统计] */
	@GetMapping(path = "/board/stats.jsonp", produces = "application/javascript;charset=UTF-8")
	@ResponseBody
	public String getBoardStatsForJsonp(
			@RequestParam("ids") String boardIdString, 
			@RequestParam("callback") String callBackFun, 
			HttpServletRequest request, 
			Model model) {
		Set<Long> boardIdSet = Commons.toLongSet(boardIdString);
		if (null==boardIdSet || boardIdSet.isEmpty()) {
			return callBackFun + "({});";
		}
		List<ForumBoardStatsRecord> data = boardStatsService.getFillTodayTopices(boardIdSet).map(ForumBoardStatsRecord::new).collect(Collectors.toList());
		if (data.isEmpty()) {
			return callBackFun + "({});";
		}
		Map<String, Object> result = new HashMap<>();
		result.put("result", data);
		Gson gson = new Gson();
		return callBackFun + "(" + gson.toJson(result) + ");";
	}

	// ----------------------------------------------------------------------版块的
	// [发布主题]指定版块组(卷)下的版块[OK]
	// 可发贴的
	@GetMapping(path = "/volumes/board.json", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public List<CommonBean> getAllBoardByBoardGroup(
			@RequestParam("volumes") int boardGroupId, 
			HttpServletRequest request, 
			Model model) {
		return boardService.getAllUsedByVolumesId(boardGroupId).stream().filter(b -> ForumEntityStatusEnum.ACTIVE == b.getStatus()).map(b -> new CommonBean(b.getId(), b.getTitle())).collect(Collectors.toList());
	}

	// 编辑
	// ETC

	// 话题移动需要的版块[OK]
	@GetMapping(path = "/board/except.jsonp", produces = "application/javascript;charset=UTF-8")
	@ResponseBody
	public String getAllBoard(
			@RequestParam("callback") String callBackFun, 
			@RequestParam(value = "box", required = false, defaultValue = "null") String boxEle, 
			@RequestParam("board") long exceptBoardId, 
			HttpServletRequest request, 
			Model model) {
		List<CommonBean> rs = boardService.getAllUsed().filter(b -> b.getId() != exceptBoardId).map(b -> new CommonBean(b.getId(), b.getTitle())).collect(Collectors.toList());
		if (rs.isEmpty()) {
			return callBackFun + "({});";
		}
		Map<String, Object> result = new HashMap<>();
		result.put("element", boxEle);
		result.put("result", rs);
		Gson gson = new Gson();
		return callBackFun + "(" + gson.toJson(result) + ");";
	}

	// 某版块的版主[OK]
	@GetMapping(path = "/board/moderator.json", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public List<CommonBean> getBoardModeratores(
			@RequestParam("id") long boardId, 
			HttpServletRequest request, 
			Model model) {
		return boardModeratorService.getAllUsedByBoardId(boardId).stream().map(bm -> new CommonBean(bm.getMemberId(), bm.getMemberNickname())).collect(Collectors.toList());
	}

	// [/home]右侧的版块统计[OK]
	@GetMapping(path = "/stats/board.json", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public List<ForumBoardStats> getBoardStats(HttpServletRequest request, Model model) {
		Map<Long, BoardStats> rs = boardStatsService.getAll().collect(Collectors.toMap(BoardStats::getBoardId, Function.identity()));
		Map<Long, String> boardNames = boardService.getAllById(rs.keySet());
		//
		List<ForumBoardStats> data = new ArrayList<>();
		for (Entry<Long, BoardStats> entry : rs.entrySet()) {
			BoardStats tmpBs = entry.getValue();
			String bn = boardNames.get(entry.getKey());
			if (null!=bn) {
				Board b = new Board();
				b.setTitle(bn);
				b.setId(entry.getKey());
				b.setVolumesId(entry.getValue().getVolumesId());
				//
				data.add(new ForumBoardStats(b, tmpBs.getPostses(), tmpBs.getTopices()));
			}
		}
		return data;
	}

	// [版块列表]底部的话题和回复统计汇总[OK]
	@GetMapping(path = "/stats/collect.json", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public Map<String, Long> getBoardStatsCollect(HttpServletRequest request, Model model) {
		Map<ForumActionEnum, Long> statsdata = boardStatsService.sumTopicAndPosts();
		Function<Entry<ForumActionEnum, Long>, String> keyMapper = entry -> {
			return ForumActionEnum.POSTS_REPLY == entry.getKey() ? "replies" : "threads";
		};
		Function<Entry<ForumActionEnum, Long>, Long> valueMapper = entry -> Commons.optional(entry.getValue(), 0L);
		return statsdata.entrySet().stream().collect(Collectors.toMap(keyMapper, valueMapper));
	}

	// ----------------------------------------------------------------------话题的
	// 某版块置顶的话题[OK]
	@GetMapping(path = "/board/top.json", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public List<ForumThreads> getBoardTopTopic(@RequestParam("board") long boardId, HttpServletRequest request, Model model) {
		return topicService.getTopForBoard(boardId).map(ForumThreads::new).collect(Collectors.toList());
	}

	// 指定版块可以发布的话题类型[OK]
	@GetMapping(path = "/board/category.json", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public List<CommonBean> getBoardTopicCategories(
			@RequestParam("volumes") int boardGroupId, 
			@RequestParam("board") long boardId, 
			HttpServletRequest request, 
			Model model) {
		Set<TopicCategory> categories = new HashSet<>();
		if (boardGroupId >= 0 && boardId > 0) {
			categories = boardTopicCategoryIndexService.getAllByBoardTopicCategories(boardGroupId, boardId).collect(Collectors.toSet());
		} else {
			categories.add(TopicCategory.empty());
		}
		return categories.stream().map(tc -> new CommonBean(tc.getId(), tc.getNames())).sorted(Comparator.comparing(CommonBean::getId)).collect(Collectors.toList());
	}

	// 版块首页(/board/home)右侧的热点话题[OK]
	@GetMapping(path = "/hot.json", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public List<ForumThreadsDigest> getHotTopices(HttpServletRequest request, Model model) {
		return topicService.getHot(10).map(ForumThreadsDigest::new).collect(Collectors.toList());
	}

	// 查看指定像册的所有图片[OK]
	@GetMapping(path = "/album.jsonp", produces = "application/javascript;charset=UTF-8")
	@ResponseBody
	public String getTopicAlbumPicturesForJsonp(
			@RequestParam("album") String albumIdString, 
			@RequestParam("callback") String callBackFun, 
			@RequestParam(value = "scale", required = false, defaultValue = "150x105") String scale, 
			@RequestParam(value = "size", required = false, defaultValue = "5") int showSize, 
			HttpServletRequest request, 
			Model model) {
		Set<Long> albumIdSet = Commons.toLongSet(albumIdString);
		if (null == albumIdSet || albumIdSet.isEmpty()) {
			return callBackFun + "({});";
		}
		// Key=像册的ID, Value=像册下的图片连接集合
		Map<Long, TreeSet<AlbumPicture>> rs = albumPictureService.getAll(albumIdSet, imageIOConfig, scale, "/static/img/140x140.png", showSize);
		Function<Entry<Long, TreeSet<AlbumPicture>>, Long> keyMapper = entry -> entry.getKey();
		Function<Entry<Long, TreeSet<AlbumPicture>>, TreeSet<ThreadsAlbumPicture>> valueMapper = entry -> entry.getValue().stream().map(ThreadsAlbumPicture::new).sorted(Comparator.comparing(ThreadsAlbumPicture::getRanking)).collect(Collectors.toCollection(TreeSet::new));
		Map<Long, TreeSet<ThreadsAlbumPicture>> result = rs.entrySet().stream().collect(Collectors.toMap(keyMapper, valueMapper));
		return callBackFun + "(" + new Gson().toJson(result) + ");";
	}

	// 话题的封面[未被使用]
	@GetMapping(path = "/cover.jsonp", produces = "application/javascript;charset=UTF-8")
	@ResponseBody
	public String getTopicCoverPictures(
			@RequestParam("topic") String topicIdString,
			@RequestParam("callback") String callBackFun, 
			@RequestParam(value = "scale", required = false, defaultValue = "150x105") String scale, 
			HttpServletRequest request, 
			Model model) {
		Set<Long> topicIdSet = Commons.toLongSet(topicIdString);
		if (null==topicIdSet || topicIdSet.isEmpty()) {
			return callBackFun + "({});";
		}
		// Key=话题的ID, Value=像册下的图片连接集合
		Map<Long, String> result = albumService.getAll(topicIdSet, imageIOConfig, scale, "/static/img/140x140.png").collect(Collectors.toMap(Album::getTopicId, Album::getCoverLink));
		return callBackFun + "(" + new Gson().toJson(result) + ");";
	}


	// ----------------------------------------------------------------------回复的

}
