package com.apobates.forum.core.entity;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.regex.PatternSyntaxException;

import javax.persistence.Basic;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.persistence.UniqueConstraint;

import com.apobates.forum.core.ad.ActiveDirectoryConnector;
import com.apobates.forum.utils.Commons;
/**
 * 话题
 * 
 * @author xiaofanku
 * @since 20190301
 */
@Entity
@Table(name = "apo_topic", uniqueConstraints = {@UniqueConstraint(columnNames = {"boardId","title"})})
public class Topic implements Serializable, Comparable<Topic>, ActiveDirectoryConnector<Topic>{
	private static final long serialVersionUID = -6074411597983125551L;
	@Id
	@GeneratedValue(strategy = GenerationType.SEQUENCE)
	private long id;
	//主题
	private String title;
	//发布日期
	private LocalDateTime entryDateTime;
	//作者:会员的ID
	private long memberId;
	private String memberNickname;
	private String ipAddr;
	//卷的ID
	private int volumesId;
	//版块的ID
	private long boardId;
	//置顶(时效)
	private boolean tops;
	//加精
	private boolean goods;
	//火贴
	private boolean hots;
	//是否有像册@20190412
	private long albumId;
	//状态
	@Basic
	@Enumerated(EnumType.STRING)
	private ForumEntityStatusEnum status;
	//显示顺序:普通话题是1,置顶的依次++
	private int ranking;
	//排序的日期
	//没有回复时为entryDateTime
	//有回复时为最近的回复日期
	private LocalDateTime rankingDateTime;
	//话题类型的参数名,年代
	private String topicCategoryName;
	//话题类型的参数值,year
	private String topicCategoryValue;
	//简述|举报和投拆不要设置此值
	private String summary;
	//是否推荐|不想被索引可以设置此值false
	//举报和投拆此值等于false|原生版块的话题此值等于false
	private boolean suggest=true;
	//是否是文章|原生版块的话题此值等于true
	private boolean article;
	@Transient
	private Set<TopicTag> tages=new HashSet<>();
	@Transient
	private TopicConfig configure; //策略模式需要(board+版主+配置文件)
	@Transient
	private TopicStats stats;
	@Transient
	private Posts content;
	//所属的版块
	@Transient
	private Board board;
	@Transient
	private BoardGroup volumes;
	@Transient
	private Album album;
	//事件需要的
	@Transient
	private String userAgent;
	
	//empty constructor for JPA instantiation
	public Topic() {super();}
	//普通话题
	public Topic(
			String title, 
			long memberId, 
			String memberNickname, 
			int volumesId,
			long boardId, 
			String ipAddr) {
		this.id = 0L;
		this.title = title;
		this.entryDateTime = LocalDateTime.now();
		this.memberId = memberId;
		this.memberNickname = memberNickname;
		this.ipAddr = ipAddr;
		this.volumesId = volumesId;
		this.boardId = boardId;
		this.tops = false;
		this.goods = false;
		this.hots = false;
		this.status = ForumEntityStatusEnum.ACTIVE;
		this.ranking = 1;
		//
		this.rankingDateTime = LocalDateTime.now();
		TopicCategory tc = TopicCategory.empty(); //普通
		this.topicCategoryName=tc.getNames();
		this.topicCategoryValue=tc.getValue();
		//
		this.suggest = true;
		this.article = false;
	}
	//含有分类的话题
	public Topic(
			String title, 
			long memberId, 
			String memberNickname, 
			int volumesId,
			long boardId, 
			String ipAddr, 
			String topicCategoryName, 
			String topicCategoryValue) {
		this.id = 0L;
		this.title = title;
		this.entryDateTime = LocalDateTime.now();
		this.memberId = memberId;
		this.memberNickname = memberNickname;
		this.ipAddr = ipAddr;
		this.volumesId = volumesId;
		this.boardId = boardId;
		this.tops = false;
		this.goods = false;
		this.hots = false;
		this.status = ForumEntityStatusEnum.ACTIVE;
		this.ranking = 1;
		//
		this.rankingDateTime = LocalDateTime.now();
		this.topicCategoryName=topicCategoryName;
		this.topicCategoryValue=topicCategoryValue;
	}
	public long getBoardId() {
		return boardId;
	}
	public boolean isTops() {
		return tops;
	}
	public boolean isGoods() {
		return goods;
	}
	public boolean isHots() {
		return hots;
	}
	public ForumEntityStatusEnum getStatus() {
		return status;
	}
	public int getRanking() {
		return ranking;
	}
	public int getVolumesId() {
		return volumesId;
	}
	public long getId() {
		return id;
	}
	public String getTitle() {
		return title;
	}
	public LocalDateTime getEntryDateTime() {
		return entryDateTime;
	}
	public long getMemberId() {
		return memberId;
	}
	public String getIpAddr() {
		return ipAddr;
	}
	public String getMemberNickname() {
		return memberNickname;
	}
	public void setMemberNickname(String memberNickname) {
		this.memberNickname = memberNickname;
	}
	public String getTopicCategoryName() {
		return topicCategoryName;
	}
	public String getTopicCategoryValue() {
		return topicCategoryValue;
	}
	public Board getBoard() {
		return board;
	}
	public BoardGroup getVolumes() {
		return volumes;
	}
	public Posts getContent() {
		return content;
	}
	public LocalDateTime getRankingDateTime() {
		return rankingDateTime;
	}
	public TopicConfig getConfigure() {
		return configure;
	}
	//--------------------------------------------SET
	public void setId(long id) {
		this.id = id;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public void setEntryDateTime(LocalDateTime entryDateTime) {
		this.entryDateTime = entryDateTime;
	}
	public void setMemberId(long memberId) {
		this.memberId = memberId;
	}
	public void setIpAddr(String ipAddr) {
		this.ipAddr = ipAddr;
	}
	public void setVolumesId(int volumesId) {
		this.volumesId = volumesId;
	}
	public void setBoardId(long boardId) {
		this.boardId = boardId;
	}
	public void setTops(boolean tops) {
		this.tops = tops;
	}
	public void setGoods(boolean goods) {
		this.goods = goods;
	}
	public void setHots(boolean hots) {
		this.hots = hots;
	}
	public void setStatus(ForumEntityStatusEnum status) {
		this.status = status;
	}
	public void setRanking(int ranking) {
		this.ranking = ranking;
	}
	public void setTopicCategoryName(String topicCategoryName) {
		this.topicCategoryName = topicCategoryName;
	}
	public void setTopicCategoryValue(String topicCategoryValue) {
		this.topicCategoryValue = topicCategoryValue;
	}
	public void setBoard(Board board) {
		this.board = board;
	}
	public void setVolumes(BoardGroup volumes) {
		this.volumes = volumes;
	}
	public void setContent(Posts content) {
		this.content = content;
	}
	public TopicStats getStats() {
		return stats;
	}
	@Transient
	public TopicStats getStatsNullOfInstance(){
		TopicStats _ts = getStats();
		if( _ts== null){
			_ts = new TopicStats(getId(), getVolumesId(), getBoardId());
		}
		return _ts;
	}
	public void setStats(TopicStats stats) {
		this.stats = stats;
	}
	public void setRankingDateTime(LocalDateTime rankingDateTime) {
		this.rankingDateTime = rankingDateTime;
	}
	public void setConfigure(TopicConfig configure) {
		this.configure = configure;
	}
	public Album getAlbum() {
		return album;
	}
	public void setAlbum(Album album) {
		this.album = album;
	}
	public long getAlbumId() {
		return albumId;
	}
	public void setAlbumId(long albumId) {
		this.albumId = albumId;
	}
	
	public Set<TopicTag> getTages() {
		return tages;
	}
	public void setTages(Set<TopicTag> tages) {
		this.tages = tages;
	}
	public String getSummary() {
		return summary;
	}
	/**
	 * 举报和投拆请不要调用此方法
	 * @param summary
	 */
	public void setSummary(String summary) {
		this.summary = summary;
	}
	public boolean isSuggest() {
		return suggest;
	}
	public void setSuggest(boolean suggest) {
		this.suggest = suggest;
	}
	public boolean isArticle() {
		return article;
	}
	public void setArticle(boolean article) {
		this.article = article;
	}
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + (int) (boardId ^ (boardId >>> 32));
		result = prime * result + ((title == null) ? 0 : title.hashCode());
		return result;
	}
	
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Topic other = (Topic) obj;
		if (boardId != other.boardId)
			return false;
		if (title == null) {
			if (other.title != null)
				return false;
		} else if (!title.equals(other.title))
			return false;
		return true;
	}
	
	@Transient
	public static Topic buildArticle(String title, long author, String authorNickname, int sectionId, long termId, String ipAdd){
		Topic article = new Topic(title, author, authorNickname, sectionId, termId, ipAdd);
		article.setStatus(ForumEntityStatusEnum.ACTIVE);
		article.setSuggest(false);
		article.setArticle(true);
		return article;
	}
	
	@Transient
	public boolean isImage(){
		return this.getAlbumId()>0;
	}
	
	@Transient
	public boolean isNormal() {
		return ForumEntityStatusEnum.ACTIVE == status;
	}
	
	@Transient
	public String getIcoStatus() {
		if(ForumEntityStatusEnum.LOCKED == getStatus()) {
			return "locked"; //锁定
		}
		if(ForumEntityStatusEnum.DELETE == getStatus()) {
			return "read"; //只读
		}
		return "normal"; //正常
	}
	
	@Transient
	public Board getLazyBoard(){
		if(getBoard()!=null){
			return getBoard();
		}
		Board b = new Board();
		b.setId(getBoardId());
		b.setVolumesId(getVolumesId());
		return b;
	}
	
	@Transient
	public static Topic empty(int volumesId, long boardId){
		Topic topic = new Topic();
		topic.setBoardId(boardId);
		topic.setVolumesId(volumesId);
		return topic;
	}
	@Transient
	public static Topic empty(long topicId){
		Topic topic = new Topic();
		topic.setId(topicId);
		return topic;
	}
	
	@Override
	public int compareTo(Topic o) {
		return rankingDateTime.compareTo(o.getRankingDateTime());
	}
	
	@Override
	public String getConnect() {
		// ${topic.id}-${topic.boardId}-${topic.volumesId}
		return getId() +"-"+ getBoardId() +"-"+ getVolumesId();
	}
	
	public String getUserAgent() {
		return userAgent;
	}
	public void setUserAgent(String userAgent) {
		this.userAgent = userAgent;
	}
	@Override
	public Optional<Topic> toConnector(String connectValue)throws IllegalStateException {
		String[] params = {};
		try{
			params = connectValue.split("-");
		}catch(NullPointerException | PatternSyntaxException e){
			throw new IllegalStateException("构造话题的ActiveDirectoryConnector实例参数不合法");
		}
		if(params.length == 0){
			throw new IllegalStateException("构造话题的ActiveDirectoryConnector实例失败");
		}
		//话题: x-x-x
		//版块: x-x
		//版块组: x
		if(params.length == 1){
			Topic topic = new Topic();
			topic.setVolumesId(Commons.stringToInteger(params[0], -1));
			return Optional.of(topic);
		}
		if(params.length == 2){
			Topic topic = new Topic();
			topic.setBoardId(Commons.stringToLong(params[0], 0L));
			topic.setVolumesId(Commons.stringToInteger(params[1], -1));
			return Optional.of(topic);
		}
		if(params.length == 3){
			Topic topic = new Topic();
			topic.setId(Commons.stringToLong(params[0], 0L));
			topic.setBoardId(Commons.stringToLong(params[1], 0L));
			topic.setVolumesId(Commons.stringToInteger(params[2], -1));
			return Optional.of(topic);
		}
		return Optional.empty();
	}
}
