package com.apobates.forum.thrones.controller;

import com.apobates.forum.attention.ImageDirectoryEnum;
import com.apobates.forum.attention.ImageStoreDomain;
import com.apobates.forum.attention.core.AvatarImagePathConvert;
import com.apobates.forum.attention.core.decorater.ForumEncoder;
import com.apobates.forum.core.entity.Topic;
import com.apobates.forum.core.entity.proxy.BoardActionCollectionReplica;
import com.apobates.forum.core.entity.proxy.BoardReplica;
import com.apobates.forum.core.entity.proxy.TopicActionCollectionReplica;
import com.apobates.forum.core.entity.proxy.TopicReplica;
import com.apobates.forum.core.service.BoardService;
import com.apobates.forum.core.service.TopicActionCollectionService;
import com.apobates.forum.core.service.TopicService;
import com.apobates.forum.event.elderly.ForumActionEnum;
import com.apobates.forum.event.elderly.MemberActionDescriptor;
import com.apobates.forum.member.MemberProfileBean;
import com.apobates.forum.member.entity.Member;
import com.apobates.forum.member.entity.MemberActiveRecords;
import com.apobates.forum.member.entity.MemberSocialInfo;
import com.apobates.forum.member.service.MemberActiveRecordsService;
import com.apobates.forum.member.service.MemberService;
import com.apobates.forum.member.service.MemberSocialInfoService;
import com.apobates.forum.member.storage.OnlineMemberStorage;
import com.apobates.forum.member.storage.core.MemberSessionBean;
import com.apobates.forum.thrones.controller.form.MemberPassportForm;
import com.apobates.forum.thrones.controller.form.MemberProfileForm;
import com.apobates.forum.thrones.controller.form.MemberSocialInfoForm;
import com.apobates.forum.thrones.controller.helper.OnlineDescriptor;
import com.apobates.forum.thrones.exception.ResourceNotFoundException;
import com.apobates.forum.thrones.vo.CommonTopic;
import com.apobates.forum.thrones.vo.ForumActionRecord;
import com.apobates.forum.thrones.vo.ForumBoardActionRecord;
import com.apobates.forum.thrones.vo.ForumBoardStats;
import com.apobates.forum.thrones.vo.ForumRankThread;
import com.apobates.forum.thrones.vo.ForumTopicActionRecord;
import com.apobates.forum.utils.Commons;
import com.apobates.forum.utils.DateTimeUtils;
import com.apobates.forum.utils.TipMessage;
import com.apobates.forum.utils.persistence.Page;
import com.apobates.forum.utils.persistence.PageRequest;
import com.google.gson.Gson;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * 会员管理中心控制器
 *
 * @author xiaofanku
 * @since 20200516
 */
@Controller
@RequestMapping(value = "/member/home")
public class MemberHomeController {
    @Autowired
    private ServletContext servletContext;
    @Autowired
    private BoardService boardService;
    @Autowired
    private TopicService topicService;
    @Autowired
    private TopicActionCollectionService topicActionCollectionService;
    @Autowired
    private MemberService memberService;
    @Autowired
    private MemberActiveRecordsService memberActiveRecordsService;
    @Autowired
    private MemberSocialInfoService memberSocialInfoService;
    @Autowired
    private OnlineMemberStorage onlineMemberStorage;
    @Autowired
    private ImageStoreDomain imageStoreDomain;
    @Value("${site.defat.avtar}")
    private String avatarDefaultDirect;
    @Value("${site.dec.salt}")
    private String globalDecSalt;
    private final static Logger logger = LoggerFactory.getLogger(MemberHomeController.class);
    
    // 会员中心|个人中心
    @GetMapping(path = "/")
    @OnlineDescriptor(action=ForumActionEnum.MEMBER_HOME)
    public String getMemberHome(
            @RequestParam(value = "token", required = false, defaultValue = "0") String token,
            MemberSessionBean mbean,
            HttpServletRequest request,
            Model model) {
        Member m = memberService.get(mbean.getMid()).orElseThrow(()->new ResourceNotFoundException("目标丢失或暂时无法访问"));
        model.addAttribute("token", token);
        //
        Map<ForumActionEnum, Long> rawdata = topicActionCollectionService.statsMemberAllAction(m.getId()); 
        MemberProfileBean memberProfile = memberService.calcMemberProfileBean(m.getId(), rawdata).orElseGet(MemberProfileBean::guest);
        Map<String, String> data = new HashMap<>(3);
        //注册日期
        data.put("logonDateTime", DateTimeUtils.formatClock(m.getRegisteDateTime()));
        //上次登录日期
        try {
            MemberActiveRecords lastLoginRecord = memberActiveRecordsService.getPreviousLoginRecord(mbean.getMid(), mbean.getNames()).orElse(null);
            String lldt = DateTimeUtils.formatClock(lastLoginRecord.getActiveDateTime());
            data.put("prevLoginDateTime", lldt);
        } catch (NullPointerException e) {
            data.put("prevLoginDateTime", "-");
        }
        data.put("names", mbean.getNames());
        model.addAttribute("member", memberProfile.toMergeMap(data));
        return "default/home/index";
    }
    
    // 会员操作历史
    @GetMapping(path = "/history")
    @OnlineDescriptor(action=ForumActionEnum.MEMBER_HISTORY)
    public String getMemberHistory(
            MemberSessionBean mbean,
            HttpServletRequest request,
            Model model) {
        model.addAttribute("total", Commons.optional(topicActionCollectionService.countByMember(mbean.getMid()), 0L));
        return "default/home/history";
    }
    @GetMapping(path = "/history/rawdata", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public String getMemberTopicActionHistory(
            @RequestParam("pageNumber") int page,
            @RequestParam("pageSize") int pageSize,
            MemberSessionBean mbean,
            HttpServletRequest request,
            Model model) {
        Page<TopicActionCollectionReplica> rs = topicActionCollectionService.getByMember(mbean.getMid(), new PageRequest(page, pageSize));
        List<ForumTopicActionRecord> data = rs.getResult().map(ForumTopicActionRecord::new).collect(Collectors.toList());
        //
        Map<String, Object> result = Map.ofEntries(Map.entry("result", data), Map.entry("total", rs.getTotalElements()), Map.entry("page", page), Map.entry("size", pageSize));
        return new Gson().toJson(result);
    }
    // 会员信息
    @GetMapping(path = "/profile")
    @OnlineDescriptor(action=ForumActionEnum.MEMBER_PROFILE_BASE)
    public String editMemberProfileForm(
            @RequestParam(value = "token", required = false, defaultValue = "0") String token,
            MemberSessionBean mbean,
            HttpServletRequest request,
            Model model) {
        MemberProfileForm form = new MemberProfileForm();
        form.setNickname(mbean.getNickname());
        form.setSignature(mbean.getSignature());
        form.setRecord(mbean.getMid());
        form.setToken(token);
        model.addAttribute("form", form);
        return "default/home/profile";
    }
    
    @PostMapping(path = "/profile")
    @OnlineDescriptor(action=ForumActionEnum.MEMBER_PROFILE_BASE)
    public String editMemberProfileAction(
            @ModelAttribute("form") MemberProfileForm form,
            MemberSessionBean mbean,
            HttpServletRequest request,
            HttpServletResponse response,
            Model model) {
        //无HTML tag,Emoji安全
        final String encodeSignatureContent = new ForumEncoder(form.getSignature()).noneHtmlTag().parseEmoji().getContent();
        boolean rmp = memberService.edit(mbean.getMid(), encodeSignatureContent, form.getNickname(), MemberController.getInstance(request, form.getToken())).orElse(false);
        if (rmp) {
            mbean = mbean.refact(form.getNickname(), encodeSignatureContent);
            onlineMemberStorage.store(mbean, request, response);
            return "redirect:/member/home/profile";
        }
        model.addAttribute("form", form);
        model.addAttribute("errors", "会员个人信息更新失败");
        return "default/home/profile";
    }
    // 社交信息
    @GetMapping(path = "/social")
    @OnlineDescriptor(action=ForumActionEnum.MEMBER_PROFILE_SOCIAL)
    public String editMemberSocialInfoForm(
            @RequestParam(value = "token", required = false, defaultValue = "0") String token,
            MemberSessionBean mbean,
            HttpServletRequest request,
            Model model) {
        MemberSocialInfoForm form = memberSocialInfoService.getByMember(mbean.getMid()).map(MemberSocialInfoForm::init).orElseGet(MemberSocialInfoForm::new);
        form.setToken(token);
        model.addAttribute("form", form);
        return "default/home/social_info";
    }
    @PostMapping(path = "/social")
    public String editMemberSocialInfoAction(
            @ModelAttribute("form") MemberSocialInfoForm form,
            MemberSessionBean mbean,
            HttpServletRequest request,
            Model model) {
        MemberActionDescriptor mad = MemberController.getInstance(request, form.getToken());
        Optional<MemberSocialInfo> rmsi;
        if (form.isUpdate()) {
            rmsi = memberSocialInfoService.edit(
                    form.getLongRecord(),
                    mbean.getMid(),
                    mbean.getNames(),
                    "nobaba",
                    form.getWeibo(),
                    form.getWeixin(),
                    form.getQq(),
                    form.getEmail(),
                    globalDecSalt, mad);
        } else {
            rmsi = memberSocialInfoService.create(
                    mbean.getMid(),
                    mbean.getNames(),
                    "nobaba",
                    form.getWeibo(),
                    form.getWeixin(),
                    form.getQq(),
                    form.getEmail(),
                    globalDecSalt, mad);
        }
        if (rmsi.isPresent()) {
            return "redirect:/member/home/profile";
        }
        model.addAttribute("form", form);
        model.addAttribute("errors", "会员社交信息更新失败");
        return "default/home/social_info";
    }
    // 编辑登录密码
    @GetMapping(path = "/passport")
    @OnlineDescriptor(action=ForumActionEnum.MEMBER_PASSPORT)
    public String editMemberPswdForm(
            @RequestParam(value = "token", required = false, defaultValue = "0") String token,
            MemberSessionBean mbean,
            HttpServletRequest request,
            Model model) {
        MemberPassportForm form = new MemberPassportForm();
        form.setToken(token);
        model.addAttribute("form", form);
        return "default/home/password";
    }
    
    @PostMapping(path = "/passport")
    @OnlineDescriptor(action=ForumActionEnum.MEMBER_PASSPORT)
    public String editMemberPswdAction(
            HttpServletRequest request,
            MemberSessionBean mbean,
            @Valid @ModelAttribute("form") MemberPassportForm form,
            BindingResult bindingResult,
            Model model) {
        if (bindingResult.hasErrors()) {
            return "default/home/password";
        }
        boolean result = memberService.editPswd(mbean.getMid(), form.getOldpswd(), form.getConfimpswd(), MemberController.getInstance(request, form.getToken())).orElse(false);
        if (result) {
            //--------------------------------------------------
            // 密码变化通知
            //--------------------------------------------------
            return "redirect:/member/home/passport/success.xhtml";
        }
        model.addAttribute("form", form);
        model.addAttribute("errors", "会员密码更新失败");
        return "default/home/password";
    }
    
    @GetMapping(path = "/passport/success.xhtml")
    public String passportSuccess(HttpServletRequest request, Model model) throws IllegalAccessException {
        //来源页判断 http Referer: site.domain{http://center.test.com}/member/home/passport
        String reqRef = request.getHeader("referer");
        if (null == reqRef || !reqRef.equals(onlineMemberStorage.getMetaConfig().getSite() + "/member/home/passport")) {
            throw new IllegalAccessException("非法的请求路径");
        }
        return "default/home/password_success";
    }
    
    @GetMapping(path = "/avatar")
    @OnlineDescriptor(action=ForumActionEnum.MEMBER_PROFILE_AVATAR)
    public String editMemberAvatarForm(
            @RequestParam(value = "token", required = false, defaultValue = "0") String token,
            MemberSessionBean mbean,
            HttpServletRequest request,
            Model model) {
        // 没有自定义目录使用
        final String direct = "default";
        List<String> defaultAvatarImages = null;
        try {
            // 方案1
            defaultAvatarImages = extractDirectFileNames(direct);
        } catch (IOException e) {
            logger.info("[AVA]extract exception :" + e.getMessage());
        }
        if (null == defaultAvatarImages || defaultAvatarImages.isEmpty()) {
            throw new ResourceNotFoundException("头像文件夹无法定位");
        }
        model.addAttribute("rs", defaultAvatarImages);
        model.addAttribute("token", token);
        // 当前选中的是哪一个
        try{
            model.addAttribute("active", AvatarImagePathConvert.getDefaultAvtarFilePath(mbean.getAvatar()));
        }catch(NullPointerException e){}
        return "default/home/avatar";
    }
    
    @PostMapping(path = "/avatar", produces = "application/json;charset=UTF-8")
    @ResponseBody
    @OnlineDescriptor(action=ForumActionEnum.MEMBER_PROFILE_AVATAR)
    public TipMessage editMemberAvatarAction(
            @RequestParam("file") String avtarPath,
            @RequestParam(value = "token", required = false, defaultValue = "0") String token,
            MemberSessionBean mbean,
            HttpServletRequest request,
            HttpServletResponse response,
            Model model) throws MalformedURLException {
        //参数avtarpath='/default/xx.png';
        String avatarURL = imageStoreDomain.getDirectoryEnumDomain(ImageDirectoryEnum.LOCAL).orElse(imageStoreDomain.getLocalDomain()) + "/" + avatarDefaultDirect + avtarPath;
        // 编码头像地址
        String encodeAvtarFormatPath = new AvatarImagePathConvert(imageStoreDomain, avatarDefaultDirect).encode(new URL(avatarURL), ImageDirectoryEnum.LOCAL).orElse(null);
        if (null != encodeAvtarFormatPath && memberService.updateAvatar(mbean.getMid(), encodeAvtarFormatPath, MemberController.getInstance(request, token)).orElse(false)) {
            mbean = mbean.refact(encodeAvtarFormatPath);
            onlineMemberStorage.store(mbean, request, response);
            // 更新mbean中的图片
            return TipMessage.ofSuccess("头像更新成功");
        }
        return TipMessage.ofError("头像更新失败");
    }
    
    @GetMapping(path = "/panel")
    public String getMemberMenu(
            @RequestParam("active") String currentMenu,
            @RequestParam(value = "token", required = false, defaultValue = "0") String token,
            MemberSessionBean mbean,
            HttpServletRequest request,
            Model model) {
        //---------------------------------------------是否来源自本站
        String requestRefString = request.getHeader("referer");
        if (null == requestRefString || !requestRefString.startsWith(onlineMemberStorage.getMetaConfig().getSite())) { // 只允许本站连接
            return "default/common/illegal_embed";
        }
        //---------------------------------------------
        model.addAttribute("manager", mbean.isManager());
        model.addAttribute("token", token);
        return "default/home/menu_embedded";
    }
    // 会员活跃的版块|会员星标的版块
    @GetMapping(path = "/board/active/json", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public List<ForumBoardStats> getMemberStarBoard(
            @RequestParam("member") long memberId, 
            @RequestParam(value = "size", required = false, defaultValue = "5") int showSize,
            HttpServletRequest request, 
            Model model) {
        Function<BoardReplica, ForumBoardStats> action = (br)->{
            return new ForumBoardStats(br, br.getStats().getPostses(), br.getStats().getTopices());
        };
        return boardService.getMemberFavorites(memberId, showSize).map(action).collect(Collectors.toList());
    }
    
    // 会员收藏的版块
    @GetMapping(path = "/board/favorite")
    public String getMemberFavoriteBoard(
            MemberSessionBean mbean,
            HttpServletRequest request,
            Model model) {
        model.addAttribute("total", Commons.optional(boardService.countFavoritesForMember(mbean.getMid()), 0L));
        return "default/home/board";
    }
    @GetMapping(path = "/board/favorite/rawdata", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public String getMemberFavoriteBoardRawdata(
            @RequestParam("pageNumber") int page,
            @RequestParam("pageSize") int pageSize,
            MemberSessionBean mbean,
            HttpServletRequest request,
            Model model) {
        Page<BoardActionCollectionReplica> rs = boardService.getFavoritesForMember(mbean.getMid(), new PageRequest(page, pageSize));
        List<ForumBoardActionRecord> data = rs.getResult().map(ForumBoardActionRecord::new).collect(Collectors.toList());
        //
        Map<String, Object> result = Map.ofEntries(Map.entry("result", data), Map.entry("total", rs.getTotalElements()), Map.entry("page", page), Map.entry("size", pageSize));
        return new Gson().toJson(result);
    }
    
    // 会员创建的话题
    @GetMapping(path = "/topic")
    public String getMemberTopic(
            MemberSessionBean mbean,
            HttpServletRequest request,
            Model model) {
        model.addAttribute("total", Commons.optional(topicService.countAllForMember(mbean.getMid()), 0L));
        return "default/home/topic";
    }
    
    @GetMapping(path = "/topic/rawdata", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public String getMemberPublishTopices(
            @RequestParam("pageNumber") int page,
            @RequestParam("pageSize") int pageSize,
            MemberSessionBean mbean,
            HttpServletRequest request,
            Model model) {
        Page<TopicReplica> rs = topicService.getAllForMember(mbean.getMid(), new PageRequest(page, pageSize));
        List<ForumActionRecord> data = rs.getResult().map(ForumActionRecord::new).collect(Collectors.toList());
        //
        Map<String, Object> result = Map.ofEntries(Map.entry("result", data), Map.entry("total", rs.getTotalElements()), Map.entry("page", page), Map.entry("size", pageSize));
        return new Gson().toJson(result);
    }
    // 会员回复的话题
    @GetMapping(path = "/posts")
    public String getMemberPosts(
            MemberSessionBean mbean,
            HttpServletRequest request,
            Model model) {
        model.addAttribute("total", Commons.optional(topicService.countAllForMemberReply(mbean.getMid()), 0L));
        return "default/home/posts";
    }
    
    @GetMapping(path = "/posts/rawdata", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public String getMemberReplyTopices(
            @RequestParam("pageNumber") int page,
            @RequestParam("pageSize") int pageSize,
            MemberSessionBean mbean,
            HttpServletRequest request,
            Model model) {
        Page<TopicReplica> rs = topicService.getAllForMemberReply(mbean.getMid(), new PageRequest(page, pageSize));
        List<ForumActionRecord> data = rs.getResult().map(ForumActionRecord::new).collect(Collectors.toList());
        //
        Map<String, Object> result = Map.ofEntries(Map.entry("result", data), Map.entry("total", rs.getTotalElements()), Map.entry("page", page), Map.entry("size", pageSize));
        return new Gson().toJson(result);
    }
    
    // 会员收藏的话题
    @GetMapping(path = "/topic/favorite")
    public String getMemeberFavoriteTopic(
            MemberSessionBean mbean,
            HttpServletRequest request,
            Model model) {
        model.addAttribute("total", Commons.optional(topicActionCollectionService.countAllByMemberAction(mbean.getMid(), ForumActionEnum.TOPIC_FAVORITE), 0L));
        return "default/home/topic_favorite";
    }
    @GetMapping(path = "/topic/favorite/rawdata", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public String getMemeberFavoriteTopicRawdata(
            @RequestParam("pageNumber") int page,
            @RequestParam("pageSize") int pageSize,
            MemberSessionBean mbean,
            HttpServletRequest request,
            Model model) {
        Page<TopicActionCollectionReplica> rs = topicActionCollectionService.getAllByMemberAction(mbean.getMid(), ForumActionEnum.TOPIC_FAVORITE, new PageRequest(page, pageSize));
        List<ForumTopicActionRecord> data = rs.getResult().map(ForumTopicActionRecord::new).collect(Collectors.toList());
        //
        Map<String, Object> result = Map.ofEntries(Map.entry("result", data), Map.entry("total", rs.getTotalElements()), Map.entry("page", page), Map.entry("size", pageSize));
        return new Gson().toJson(result);
    }
    // 会员点赞的话题
    @GetMapping(path = "/topic/like")
    public String getMemberLikeTopic(
            MemberSessionBean mbean,
            HttpServletRequest request,
            Model model) {
        model.addAttribute("total", Commons.optional(topicActionCollectionService.countAllByMemberAction(mbean.getMid(), ForumActionEnum.TOPIC_LIKED), 0L));
        return "default/home/topic_like";
    }
    @GetMapping(path = "/topic/like/rawdata", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public String getMemberLikeTopicRawdata(
            @RequestParam("pageNumber") int page,
            @RequestParam("pageSize") int pageSize,
            MemberSessionBean mbean,
            HttpServletRequest request,
            Model model) {
        Page<TopicActionCollectionReplica> rs = topicActionCollectionService.getAllByMemberAction(mbean.getMid(), ForumActionEnum.TOPIC_LIKED, new PageRequest(page, pageSize));
        List<ForumTopicActionRecord> data = rs.getResult().map(ForumTopicActionRecord::new).collect(Collectors.toList());
        //
        Map<String, Object> result = Map.ofEntries(Map.entry("result", data), Map.entry("total", rs.getTotalElements()), Map.entry("page", page), Map.entry("size", pageSize));
        return new Gson().toJson(result);
    }
    
    // 会员最近发布的话题
    @GetMapping(path = "/topic/publish/json", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public List<CommonTopic> getMemberRecentPublishTopic(
            @RequestParam("member") long memberId,
            @RequestParam(value = "size", required = false, defaultValue = "5") int showSize,
            HttpServletRequest request,
            Model model) {
        int showRecordSize = (showSize > 10 || showSize < 1) ? 5 : showSize;
        return topicService.getRecentForMember(memberId, showRecordSize).sorted(Comparator.comparing(Topic::getEntryDateTime).reversed()).map(CommonTopic::new).collect(Collectors.toList());
    }
    
    // 会员最近回复的话题
    @GetMapping(path = "/topic/reply/json", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public List<CommonTopic> getMemberRecentReply(
            @RequestParam("member") long memberId,
            @RequestParam(value = "size", required = false, defaultValue = "5") int showSize,
            HttpServletRequest request,
            Model model) {
        int showRecordSize = (showSize > 10 || showSize < 1) ? 5 : showSize;
        return topicService.getAllForMemberReply(memberId, showRecordSize).sorted(Comparator.comparing(Topic::getRankingDateTime).reversed()).map(CommonTopic::new).collect(Collectors.toList());
    }
    // 会员受欢迎的话题
    @GetMapping(path = "/topic/popular/json", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public List<ForumRankThread> getMemberPopularTopic(
            @RequestParam(value = "size", required = false, defaultValue = "5") int showSize,
            MemberSessionBean mbean,
            HttpServletRequest request,
            Model model) {
        int showRecordSize = (showSize > 10 || showSize < 1) ? 5 : showSize;
        Comparator<TopicReplica> c = (TopicReplica o1, TopicReplica o2) -> {
            if(o1.getStats().getDisplaies() == o2.getStats().getDisplaies()){
                return 0;
            }
            if(o1.getStats().getDisplaies() > o2.getStats().getDisplaies()){
                return 1;
            }
            return -1;
        };
        AtomicInteger index = new AtomicInteger(0);
        Function<TopicReplica,ForumRankThread> mapper = ts->{
            int rk = index.getAndIncrement();
            return new ForumRankThread(ts, rk);
        };
        return topicService.getAllForMemberPopular(mbean.getMid(), showRecordSize).sorted(c.reversed()).map(mapper).collect(Collectors.toList());
    }
    // 方案1
    // SpringBoot可以与SSM共存.
    // SpringBoot需要在war所在的目录放一个avatar文件夹(里面需要avatarTheme这个子文件夹,子文件夹中包含图片)
    private List<String> extractDirectFileNames(final String avatarTheme) throws FileNotFoundException {
        Objects.requireNonNullElseGet(avatarTheme, ()->new FileNotFoundException("头像文件夹无法定位"));
        final String fileRealPath = servletContext.getRealPath(avatarDefaultDirect + "/" + avatarTheme + "/");
        final String replaceString = onlineMemberStorage.getMetaConfig().getSite() + "/" + avatarDefaultDirect + "/" + avatarTheme + "/";
        //
        List<String> result = new ArrayList<>();
        try{
            try(Stream<Path> sp = Files.list(Paths.get(fileRealPath))){
                result = sp.parallel().map((Path p)->{
                    return p.toAbsolutePath().toString().replace(fileRealPath, replaceString);
                }).filter(fn->!fn.endsWith(".html")).collect(Collectors.toList());
            }
        }catch(IOException e){
            if(logger.isDebugEnabled()){
                logger.debug("头像文件夹遍历失败", e);
            }
        }
        return result;
    }
}