package com.apobates.forum.core.api.service;

import java.io.File;
import java.time.LocalDateTime;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.TreeMap;
import java.util.function.Function;
import java.util.stream.Stream;
import com.apobates.forum.core.api.ImageIOMeta;
import com.apobates.forum.core.api.TagRelateTopic;
import com.apobates.forum.core.api.TopicFileCache;
import com.apobates.forum.core.entity.Board;
import com.apobates.forum.core.entity.ForumEntityStatusEnum;
import com.apobates.forum.core.entity.Topic;
import com.apobates.forum.core.entity.TopicConfig;
import com.apobates.forum.core.plug.AbstractPlugTopic;
import com.apobates.forum.core.plug.PlugTopic;
import com.apobates.forum.event.elderly.ActionEventCulpritor;
import com.apobates.forum.event.elderly.ForumActionEnum;
import com.apobates.forum.member.entity.Member;
import com.apobates.forum.utils.persistence.Page;
import com.apobates.forum.utils.persistence.Pageable;
/**
 * 话题的业务接口
 * 
 * @author xiaofanku
 * @since 20190326
 */
public interface TopicService {
	/**
	 * 发布[普通]话题, 操作成功后会发送通知(TopicPublishEvent)
	 * 
	 * @param volumesId 版块组(卷)ID
	 * @param boardId   版块ID
	 * @param title     话题主题
	 * @param content   话题内容
	 * @param imageIO   图片存储信息
	 * @param culpritor 操作的肇事信息
	 * @return
	 */
	long create(int volumesId, long boardId, String title, String content, ImageIOMeta imageIO, ActionEventCulpritor culpritor);
	
	/**
	 * [前台]发布指定类型的话题, 操作成功后会发送通知(TopicPublishEvent)
	 * 
	 * @param volumesId  版块组(卷)ID
	 * @param boardId    版块ID
	 * @param categoryId 话题类型ID,等于0等同于普通
	 * @param title      话题主题
	 * @param content    话题内容
	 * @param imageIO    图片存储信息
	 * @param culpritor  操作的肇事信息
	 * @return
	 */
	long create(int volumesId, long boardId, int categoryId, String title, String content, ImageIOMeta imageIO, ActionEventCulpritor culpritor);
	
	/**
	 * [后台]发布指定类型的话题, 操作成功后会发送通知(TopicPublishEvent)
	 * 
	 * @param volumesId     版块组(卷)ID
	 * @param boardId       版块ID
	 * @param categoryName  话题类型名称
	 * @param categoryValue 话题类型参数值
	 * @param title         话题主题
	 * @param content       话题内容
	 * @param keywords      话题标签称数组
	 * @param imageIO       图片存储信息
	 * @param culpritor     操作的肇事信息
	 * @return
	 */
	long create(int volumesId, long boardId, String categoryName, String categoryValue, String title, String content, String[] keywords, ImageIOMeta imageIO, ActionEventCulpritor culpritor)throws IllegalStateException;
	
	/**
	 * 发布文章, 操作成功后会发送通知(TopicPublishEvent)
	 * @since 20200427
	 * @param sectionId 栏目ID
	 * @param termId    子栏目ID
	 * @param title     文章标题
	 * @param content   文章内容
	 * @param imageIO   图片存储信息
	 * @param culpritor 操作的肇事信息
	 * @return
	 */
	long createTermArticle(int sectionId, long termId, String title, String content, ImageIOMeta imageIO, ActionEventCulpritor culpritor)throws IllegalStateException;
	
	/**
	 * 置顶话题
	 * 
	 * @param id        话题ID
	 * @param culpritor 操作的肇事信息
	 * @return
	 */
	Optional<Boolean> editTop(long id, ActionEventCulpritor culpritor)throws IllegalStateException;

	/**
	 * 取消话题的置顶
	 * 
	 * @param id        话题ID
	 * @param culpritor 操作的肇事信息
	 * @return
	 */
	Optional<Boolean> removeTop(long id, ActionEventCulpritor culpritor)throws IllegalStateException;

	/**
	 * 加精话题
	 * 
	 * @param id        话题ID
	 * @param culpritor 操作的肇事信息
	 * @return
	 */
	Optional<Boolean> editGoods(long id, ActionEventCulpritor culpritor);

	/**
	 * 取消话题的加精
	 * 
	 * @param id        话题ID
	 * @param culpritor 操作的肇事信息
	 * @return
	 */
	Optional<Boolean> removeGoods(long id, ActionEventCulpritor culpritor);
	
	/**
	 * 话题点赞
	 * 
	 * @param id        话题ID
	 * @param culpritor 操作的肇事信息
	 * @return
	 */
	Optional<Boolean> like(long id, ActionEventCulpritor culpritor)throws IllegalStateException;
	
	/**
	 * 取消会员的点赞
	 * 
	 * @param id        话题ID
	 * @param culpritor 操作的肇事信息
	 * @return
	 */
	Optional<Boolean> removeLike(long id, ActionEventCulpritor culpritor)throws IllegalStateException;
	
	/**
	 * 锁定话题
	 * 
	 * @param id        话题ID
	 * @param culpritor 操作的肇事信息
	 * @return
	 */
	Optional<Boolean> lock(long id, ActionEventCulpritor culpritor)throws IllegalStateException;

	/**
	 * 解锁锁定的话题
	 * 
	 * @param id        话题ID
	 * @param culpritor 操作的肇事信息
	 * @return
	 */
	Optional<Boolean> releaseLock(long id, ActionEventCulpritor culpritor)throws IllegalStateException;

	/**
	 * 删除话题
	 * 
	 * @param id        话题ID
	 * @param culpritor 操作的肇事信息
	 * @return
	 */
	Optional<Boolean> remove(long id, ActionEventCulpritor culpritor)throws IllegalStateException;
	
	/**
	 * 删除子栏目的文章
	 * @since 20200427
	 * @param id        子栏目的文章ID
	 * @param termId    子栏目的ID
	 * @param culpritor 操作的肇事信息
	 * @return
	 */
	Optional<Boolean> removeTermArticle(long id, long termId, ActionEventCulpritor culpritor);
	
	/**
	 * 收藏话题
	 * 
	 * @param id        话题ID
	 * @param culpritor 操作的肇事信息
	 * @return
	 */
	Optional<Boolean> favorite(long id, ActionEventCulpritor culpritor)throws IllegalStateException;
	
	/**
	 * 取消会员的收藏
	 * 
	 * @param id        话题ID
	 * @param culpritor 操作的肇事信息
	 * @return
	 */
	Optional<Boolean> removeFavorite(long id, ActionEventCulpritor culpritor)throws IllegalStateException;
	
	/**
	 * 是否可以点赞, 可以返回true
	 * 
	 * @param id       话题ID
	 * @param memberId 会员ID
	 * @return
	 */
	boolean isLiked(long id, long memberId);
	
	/**
	 * 是否可以收藏, 可以返回true
	 * 
	 * @param id       话题ID
	 * @param memberId 会员ID
	 * @return
	 */
	boolean isFavorited(long id, long memberId);
	
	/**
	 * 浏览话题
	 * 
	 * @param id        话题ID
	 * @param culpritor 操作的肇事信息
	 * @return
	 */
	Optional<Boolean> browse(long id, ActionEventCulpritor culpritor)throws IllegalStateException;
	/**
	 * 移动话题, 操作成功后会发送通知(TopicMoveEvent)
	 * 
	 * @param id            话题ID
	 * @param boardId       现在的版块ID
	 * @param targetBoardId 目标版块ID
	 * @param culpritor     操作的肇事信息
	 * @return
	 */
	Optional<Boolean> move(long id, long boardId, long targetBoardId, ActionEventCulpritor culpritor)throws IllegalStateException;

	/**
	 * 执行编辑话题配置检查,适用于前端执行,会进行话题作者,版主身份检测
	 * 
	 * @param id           话题ID
	 * @param updateConfig 更新的话题配置实例
	 * @param configId     话题配置ID
	 * @param culpritor    操作的肇事信息
	 * @return
	 */
	Optional<Boolean> editTopicConfig(long id, TopicConfig updateConfig, long configId, ActionEventCulpritor culpritor)throws IllegalStateException;
	
	/**
	 * 编辑话题
	 * 
	 * @param id        话题ID
	 * @param title     主题
	 * @param content   内容
	 * @param keywords  关键词
	 * @param imageIO   图片存储信息
	 * @param culpritor 操作的肇事信息
	 * @return
	 */
	Optional<Boolean> edit(long id, String title, String content, String[] keywords, ImageIOMeta imageIO, ActionEventCulpritor culpritor)throws IllegalStateException;
	
	/**
	 * 编辑文章
	 * @since 20200427
	 * @param articleId 文章ID
	 * @param title     主题
	 * @param content   内容
	 * @param imageIO   图片存储信息
	 * @param culpritor 操作的肇事信息
	 * @return
	 */
	Optional<Boolean> editTermArticle(long articleId, String title, String content, ImageIOMeta imageIO, ActionEventCulpritor culpritor)throws IllegalStateException;
	
	/**
	 * 查看指定话题的海报
	 * 
	 * @param id         话题ID
	 * @param posterURL  海报的访问地址
	 * @param tfc        缓存Topic相关的File
	 * @param culpritor  操作的肇事信息
	 * @return 
	 */
	Optional<File> getPoster(long id, String posterURL, TopicFileCache tfc, ActionEventCulpritor culpritor)throws IllegalStateException;
	
	/**
	 * 查看指定版块下的所有话题,不包括删除,置顶;包括加精,普通;级联加载话题统计
	 * 
	 * @param boardId  版块ID
	 * @param pageable 分页请求参数
	 * @return
	 */
	Page<Topic> getAll(long boardId, Pageable pageable);
	
	/**
	 * 查看指定版块下的指定类型的话题,不包括删除,置顶;包括加精,普通;级联加载话题统计
	 * 
	 * @param boardId       版块ID
	 * @param categoryValue 话题类型的Key(Topic.topicCategoryValue = TopicCategory.value)
	 * @param pageable      分页请求参数
	 * @return
	 */
	Page<Topic> getAll(long boardId, String categoryValue, Pageable pageable);
	
	/**
	 * 查看指定会员发布的所有话题,会级联加载话题统计
	 * 
	 * @param memberId 会员ID
	 * @param pageable 分页请求参数
	 * @return
	 */
	Page<Topic> getAllForMember(long memberId, Pageable pageable);
	
	/**
	 * 统计会员发布话题的总数
	 * 
	 * @param memberId 会员ID
	 * @return
	 */
	long countAllForMember(long memberId);
	
	/**
	 * 查看会员回复的话题,话题的作者不是该会员(不包含自已发的),会级联加载话题的统计
	 * 
	 * @param memberId 会员ID
	 * @param pageable 分页请求参数
	 * @return
	 */
	Page<Topic> getAllForMemberReply(long memberId, Pageable pageable);
	
	/**
	 * 统计会员回复的总数
	 * 
	 * @param memberId 会员ID
	 * @return
	 */
	long countAllForMemberReply(long memberId);
	
	/**
	 * 查看指定子栏目下的所有文章
	 * @since 20200427
	 * @param termId   子栏目ID
	 * @param pageable 分页请求参数
	 * @return
	 */
	Page<Topic> getTermArticle(long termId, Pageable pageable);
	
	/**
	 * 根据标签查看相关的话题
	 * 
	 * @param tagNames 标签名称
	 * @param pageable 分页请求参数
	 * @return
	 */
	Page<Topic> getAllForTag(List<String> tagNames, Pageable pageable);
	
	/**
	 * 查看指定版块最近的话题,不包括删除,置顶;包括加精,普通;以rankingDateTime倒序
	 * 服务于RSS
	 * 
	 * @param boardId 版块ID
	 * @param size    显示的数量
	 * @return
	 */
	Stream<Topic> getRecentForBoard(long boardId, int size);
	
	/**
	 * 查看指定版块最近的话题, 忽略状态;以entryDateTime倒序
	 * 服务于策略检查
	 * 
	 * @param boardId 版块ID
	 * @param size    显示的数量
	 * @return
	 */
	Stream<Topic> getRecentForBoardIgnoreStatus(long boardId, int size);
	
	/**
	 * 指定版块置顶的话题,不包括删除;会级联加载话题统计
	 * 
	 * @param boardId 版块ID
	 * @return
	 */
	Stream<Topic> getTopForBoard(long boardId);
	
	/**
	 * 查看指定会员最近发布的话题,级联加载版块
	 * 
	 * @param memberId 会员ID
	 * @param size     显示的数量
	 * @return
	 */
	Stream<Topic> getRecentForMember(long memberId, int size);

	/**
	 * 查看指定会员最近回复的话题,话题的作者不是该会员(不包含自已发的),级联加载版块
	 * 
	 * @param memberId 会员ID
	 * @param size     显示的数量
	 * @return
	 */
	Stream<Topic> getAllForMemberReply(long memberId, int size);
	
	/**
	 * 查看会员发布的受欢迎的话题列表,级联加载版块,话题统计
	 * 
	 * @param memberId 会员ID
	 * @param size     显示的数量
	 * @return
	 */
	Stream<Topic> getAllForMemberPopular(long memberId, int size);
	
	/**
	 * 查看最近发布的话题,不包括删除的,不包含1号(举报和反馈所在)版块的
	 * 
	 * @param size 显示的数量
	 * @return
	 */
	Stream<Topic> getRecent(int size);
	
	/**
	 * 查看最近发布的话题,不建议前台使用,包含所有版块,所有状态的
	 * 
	 * @param size 显示的数量
	 * @return
	 */
	Stream<Topic> getRecentIgnoreCondition(int size);
	
	/**
	 * 查看指定版块组最近发布的话题,方法将级联加载话题统计
	 * 
	 * @param boardGroupId 版块组(卷)ID
	 * @param size         显示的数量
	 * @return
	 */
	Stream<Topic> getRecent(int boardGroupId, int size);
	
	/**
	 * 查看指定版块组(卷)下的精华话题
	 * 
	 * @param boardGroupId 版块组(卷)ID
	 * @param size         显示的数量
	 * @return
	 */
	Stream<Topic> getGoodsForBoardGroup(int boardGroupId, int size);
	
	/**
	 * 查看指定版块组(卷)下的最多回复的话题
	 * 
	 * @param boardGroupId 版块组(卷)ID
	 * @param size         显示的数量
	 * @return
	 */
	Stream<Topic> getMaxReplyForBoardGroup(int boardGroupId, int size);
	
	/**
	 * 查看回复最多的话题
	 * 
	 * @param size 显示的数量
	 * @return
	 */
	Stream<Topic> getHot(int size);
	
	/**
	 * 按回复时间查看指定的话题
	 * 
	 * @param size 显示的数量
	 * @return
	 */
	Stream<Topic> getRecentReply(int size);
	
	/**
	 * 查看版块的话题列表,最先发布的排在最前面(Topic.entryDateTime ASC)
	 * 
	 * @param boardId 版块ID
	 * @param status  话题的状态
	 * @return
	 */
	Stream<Topic> getAllByBoard(long boardId, ForumEntityStatusEnum status);
	
	/**
	 * 最近子栏目发布的文章列表,此方法有别与以下方法
	 * getRecentIgnoreCondition
	 * getRecentRelateContent
	 * getRecent
	 * @since 20200427
	 * @param size 显示的数量
	 * @return
	 */
	Stream<Topic> getRecentTermArticle(int size);

	/**
	 * 查看指定话题相关的话题
	 * 
	 * @param id   话题ID
	 * @param size 显示的数量
	 * @return
	 */
	Stream<TagRelateTopic> getRelateTopic(long id, int size);
	
	/**
	 * 查看最近发布的话题,不包括删除的,不包含1号(举报和反馈所在)版块的.方法会级联加载版块,话题统计
	 * 
	 * @param size 显示的数量
	 * @return
	 */
	List<Topic> getRecentRelateContent(int size);
	
	/**
	 * 自参考日期以后版块最近的话题,会级联加载话题统计
	 * 
	 * @param boardId       版块ID
	 * @param prevUnixStamp 参考日期
	 * @return
	 */
	List<Topic> getRecentByUnixStamp(long boardId, int prevUnixStamp);
	
	/**
	 * 查看指定的话题
	 * 
	 * @param id 话题ID
	 * @return
	 */
	Optional<Topic> get(long id);

	/**
	 * 如果话题存在会关联相关对象:统计
	 * 
	 * @param id 话题ID
	 * @return
	 */
	Topic getTopicStats(long id);
	
	/**
	 * 查看指定话题, 级联加载版块组(卷), 版块
	 * 
	 * @param id           话题ID
	 * @param boardId      版块ID
	 * @param boardGroupId 版块组(卷)ID
	 * @return
	 */
	Topic get(long id, long boardId, int boardGroupId);
	
	/**
	 * 查看指定话题, 级联加载版块
	 * 
	 * @param id      话题ID
	 * @param boardId 版块ID
	 * @return
	 */
	Topic get(long id, long boardId);
	
	/**
	 * 如果话题存在会级联加载话题配置
	 * 
	 * @param id 话题ID
	 * @return
	 */
	Topic getTopicConfig(long id);
	
	/**
	 * 查看指定的话题,加载话题的内容并且对内容进行解码(若内容中含有图片进行懒加载),加载话题的统计信息
	 * [后台查看话题]
	 * @param id      话题ID
	 * @param imageIO 图片存储信息
	 * @return
	 */
	Topic getTopicContentAndStats(long id, ImageIOMeta imageIO);
	
	/**
	 * 查看指定的话题,加载话题的内容并且对内容进行解码(若内容中含有图片进行懒加载),加载话题的统计信息
	 * 
	 * @param id                 话题ID
	 * @param imageIO            图片存储信息
	 * @param dictionaryFilePath 敏感词库所在的位置
	 * @return
	 */
	Topic getTopicContentAndStatsForRSS(long id, ImageIOMeta imageIO, String dictionaryFilePath);
	
	/**
	 * 查看子栏目中指定的文章内容并且对内容进行解码(若内容中含有图片进行懒加载)
	 * @since 20200427
	 * @param id      文章ID
	 * @param imageIO 图片存储信息
	 * @return
	 */
	Topic getTermArticleContent(long id, ImageIOMeta imageIO);
	
	/**
	 * 查看指定的话题,加载话题的内容,加载话题的统计信息(前端话题内容页)
	 * 
	 * @param id 话题ID
	 * @param topicAuthorFun 话题作者映射函数,不需要映射传入null
	 * @return
	 */
	Topic getTopicContentAndStats(long id, Function<Long, Optional<Member>> topicAuthorFun);
	
	/**
	 * 查看指定的话题,加载话题的内容(话题标签相关)
	 * 
	 * @param id 话题ID
	 * @param topicAuthorFun 话题作者映射函数,不需要映射传入null
	 * @return
	 */
	Topic getTopicContent(long id, Function<Long, Optional<Member>> topicAuthorFun);
	
	/**
	 * 查看栏目中的第一篇文章. 加载话题的内容并且对内容进行解码(若内容中含有图片进行懒加载)
	 * @since 20200427
	 * @param termId  子栏目ID
	 * @param imageIO 图片存储信息
	 * @return
	 */
	Topic getFirstArticleForTerm(long termId, ImageIOMeta imageIO);
	
	/**
	 * 统计版块今天的话题数量
	 * 
	 * @return
	 */
	Map<Long,Long> statsBoardTopicesForToday();
	
	/**
	 * 统计版块在指定日期的话题数量
	 * 
	 * @param start  开始日期
	 * @param finish 结束日期
	 * @return Key=版块ID, Value=话题数量
	 */
	Map<Long,Long> statsBoardTopicesForDate(LocalDateTime start, LocalDateTime finish);
	
	/**
	 * 分组统计指定日期范围内的每日话题数量
	 * 
	 * @param start  开始日期
	 * @param finish 结束日期
	 * @return Key=YYYY-MM-DD, Value=话题数量
	 */
	TreeMap<String,Long> groupTopicesForDate(LocalDateTime start, LocalDateTime finish);
	
	/**
	 * 分组统计不同状态的话题数量
	 * 
	 * @return Key=Topic.status, Value=话题数量
	 */
	EnumMap<ForumEntityStatusEnum,Long> groupTopicesForStatus();
	
	/**
	 * 分组统计不同分类的话题数量
	 * 
	 * @return Key=Topic.topicCategoryName, Value=话题数量
	 */
	Map<String,Long> groupTopicesForCategory();
	
	/**
	 * 分组统计不同版块的话题数量.版块统计内有此数据
	 * 
	 * @return Key=Topic.boardId, Value=话题数量
	 */
	Map<Board,Long> groupTopicesForBoard();
	
	/**
	 * 查看子栏目中指定文章上一篇和下一篇文章
	 * @since 20200427
	 * @param termId    子栏目ID
	 * @param articleId 文章ID
	 * @return key = PREV|NEXT value = 上一条话题|下一条话题,Key不存在表示不存在对应的话题
	 */
	Map<String,Topic> getPrevNextTermArticle(long termId, long articleId);
	/**
	 * 
	 * @param topicBuildPlug
	 * @return
	 */
	Optional<Topic> plug(AbstractPlugTopic topicBuildPlug);
	
	/**
	 * 
	 * @param topicBuildPlug
	 * @param action
	 * @param culpritor
	 * @return
	 */
	Optional<Topic> plug(PlugTopic topicBuildPlug, final ForumActionEnum action, final ActionEventCulpritor culpritor);
	
}
