package com.apobates.forum.thrones.controller;

import com.apobates.forum.core.entity.proxy.PostsReplica;
import com.apobates.forum.core.entity.proxy.TopicReplica;
import com.apobates.forum.core.security.exposure.impl.TopicDetectionStrategy;
import com.apobates.forum.core.security.strategy.Strategy;
import com.apobates.forum.core.security.strategy.StrategyEntityParam;
import com.apobates.forum.core.service.PostsService;
import com.apobates.forum.core.service.TopicTagService;
import com.apobates.forum.event.elderly.ActionEventCulpritor;
import com.apobates.forum.event.elderly.ForumActionEnum;
import com.apobates.forum.member.entity.MemberRoleEnum;
import com.apobates.forum.member.storage.core.MemberSessionBean;
import com.apobates.forum.thrones.controller.helper.OnlineDescriptor;
import com.apobates.forum.utils.lang.CommonBean;
import com.apobates.forum.utils.Commons;
import com.apobates.forum.utils.StringSeekUtils;
import com.apobates.forum.utils.TipMessage;
import com.apobates.forum.utils.TipMessageLevelEnum;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
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.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * 话题标签控制器
 *
 * @author xiaofanku
 * @author 20200526
 */
@Controller
@RequestMapping(value = "/topic/tag")
public class TopicTagController {
    @Autowired
    private TopicTagService topicTagService;
    @Autowired
    private PostsService postsService;
    @Value("${site.domain}")
    private String siteDomain;
    
    //删除(版主和管理员)
    @PostMapping(path = "/delete", produces = "application/json;charset=UTF-8")
    @ResponseBody
    @OnlineDescriptor(action=ForumActionEnum.TOPIC_TAG_DEL)
    @Strategy(action=ForumActionEnum.TOPIC_TAG_DEL, param=StrategyEntityParam.REFERER, allowRoles={MemberRoleEnum.ADMIN, MemberRoleEnum.MASTER, MemberRoleEnum.BM}, handler=TopicDetectionStrategy.class)
    public TipMessage deleteTagAction(
            @RequestParam("id") long tagId,
            @RequestHeader(value = "referer", required = false, defaultValue = "") final String referer,
            @RequestParam(value = "token", required = false, defaultValue = "0") String token,
            MemberSessionBean mbean,
            HttpServletRequest request,
            Model model) {
        //------------------------------来源的话题
        TopicReplica tpObj = TopicReplica.of(referer, siteDomain).orElse(null);
        if (null == tpObj || tpObj.getId() < 1) {
            return TipMessage.ofError("因参数丢失操作被中断");
        }
        //------------------------------权限检查
        //  移至StrategyInterceptorAdapter
        //------------------------------
        ActionEventCulpritor aec = BoardController.getInstance(mbean.getMid(), mbean.getNickname(), request, token);
        return TipMessage.Builder.take(()->topicTagService.deleteForTopic(tpObj.getId(), tagId, aec)).success("标签成功删除").error("操作失败");
    }
    
    //添加(并统计词频)(版主和管理员)
    @PostMapping(path = "/add", produces = "application/json;charset=UTF-8")
    @ResponseBody
    @OnlineDescriptor(action=ForumActionEnum.TOPIC_TAG_ADD)
    @Strategy(action=ForumActionEnum.TOPIC_TAG_ADD, param=StrategyEntityParam.REFERER, allowRoles={MemberRoleEnum.ADMIN, MemberRoleEnum.MASTER, MemberRoleEnum.BM}, handler=TopicDetectionStrategy.class)
    public TipMessage createTagAction(
            @RequestParam("names") String tagNames,
            @RequestHeader(value = "referer", required = false, defaultValue = "") final String referer,
            @RequestParam(value = "token", required = false, defaultValue = "0") String token,
            MemberSessionBean mbean,
            HttpServletRequest request,
            Model model) {
        //------------------------------来源的话题
        TopicReplica tpObj = TopicReplica.of(referer, siteDomain).orElse(null);
        if (null == tpObj || tpObj.getId() < 1) {
            return TipMessage.ofError("因参数丢失操作被中断");
        }
        //------------------------------权限检查
        //  移至StrategyInterceptorAdapter
        //------------------------------获取话题的内容以便词频统计
        Optional<PostsReplica> posts = postsService.getTopicContent(tpObj.getId());
        if (!posts.isPresent()) {
            return TipMessage.ofError("因异常操作被中断");
        }
        PostsReplica pr = posts.get();
        //过滤一下
        String newTagNames = Commons.htmlPurifier(tagNames).trim();
        int rates = StringSeekUtils.queryWordCountByBM(pr.getTopic().getTitle() + " " + pr.getContent(), newTagNames);
        //
        ActionEventCulpritor aec = BoardController.getInstance(mbean.getMid(), mbean.getNickname(), request, token);
        long id = topicTagService.create(tpObj.getId(), newTagNames, rates, aec);
        if (id > 0) {
            return new TipMessage("标签添加成功", TipMessageLevelEnum.ACC, id + "");
        }
        return TipMessage.ofError("操作失败");
    }
    
    //热点标签(从Tag中找出现最多的标签)
    @GetMapping(path = "/hot.json", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public List<CommonBean> getHotTopicTag(
            HttpServletRequest request,
            Model model) {
        Map<String, Long> rs = topicTagService.groupTagForNames(10);
        LinkedHashMap<String, Long> result = rs.entrySet().stream().sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue, LinkedHashMap::new));
        //
        return result.entrySet().stream().map((entry)->new CommonBean(entry.getValue(), entry.getKey())).collect(Collectors.toList());
    }
}