package com.apobates.forum.core.entity.proxy;

import com.apobates.forum.core.entity.Album;
import com.apobates.forum.core.entity.Board;
import com.apobates.forum.core.entity.BoardGroup;
import com.apobates.forum.core.entity.Posts;
import com.apobates.forum.core.entity.Topic;
import com.apobates.forum.core.entity.TopicConfig;
import com.apobates.forum.core.entity.TopicStats;
import com.apobates.forum.core.entity.TopicTag;
import com.apobates.forum.member.entity.Member;
import com.apobates.forum.utils.Commons;
import com.apobates.forum.utils.lang.ForumReplicable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author xiaofanku
 * @since 20200513
 */
public final class TopicReplica extends Topic implements ActiveDirectoryConnector<TopicReplica>, ForumReplicable<Topic,TopicReplica>{
    private Set<TopicTag> tages=new HashSet<>();
    private TopicConfig configure; //策略模式需要(board+版主+配置文件)
    private TopicStats stats;
    private PostsReplica content;
    //所属的版块
    private BoardReplica board;
    private BoardGroup volumes;
    private Album album;
    private Member author;
    //事件需要的
    private String userAgent;
    private final static Pattern TOPIC_URL_PARSE = Pattern.compile("/topic/(.*).xhtml");
    private final static Logger logger = LoggerFactory.getLogger(TopicReplica.class);
    public static Function<Topic, TopicReplica> copyTopic = (topic) -> {
        return ForumReplicable.replica(topic, TopicReplica.class).orElseGet(TopicReplica::new);
    };
    
    public TopicReplica() {
    }
    
    public static Optional<TopicReplica> of(String connectValue){
        try{
            return new TopicReplica().toConnector(connectValue);
        }catch(IllegalStateException e){
            return Optional.empty();
        }
    }
    public static Optional<TopicReplica> of(String requestRefString, String siteDomain) {
        if (requestRefString == null || !requestRefString.startsWith(siteDomain)) { // 只允许本站连接
            return Optional.empty();
        }
        //
        Matcher m = TOPIC_URL_PARSE.matcher(requestRefString);
        String connectValue = null;
        if (m.find()) {
            connectValue = m.group(1);
        }
        return of(connectValue);
    }
    //
    public Set<TopicTag> getTages() {
        return tages;
    }
    public void setTages(Collection<TopicTag> tages){
        this.tages.addAll(tages);
    }
    public void setTages(Stream<TopicTag> tages){
        this.tages.addAll(tages.collect(Collectors.toSet()));
    }
    //
    public TopicConfig getConfigure() {
        return configure;
    }
    public void setConfigure(TopicConfig config){
        this.configure = config;
    }
    //
    public TopicStats getStats() {
        return stats;
    }
    public void setStats(TopicStats stats){
        this.stats = stats;
    }
    //
    public PostsReplica getContent() {
        return content;
    }
    public void setContent(PostsReplica posts) {
        this.content = posts;
    }
    public void copyContent(Posts posts){
        this.content = Optional.ofNullable(posts).map(PostsReplica.copyPosts).orElseGet(PostsReplica::new);
    }
    //
    public BoardReplica getBoard() {
        return board;
    }
    
    public void copyBoard(Board board){
        this.board = Optional.ofNullable(board).map(BoardReplica.copyBoard).orElse(null);
    }
    public void setBoard(BoardReplica board){
        this.board = board;
    }
    //
    public BoardGroup getVolumes() {
        return volumes;
    }
    public void setVolumes(BoardGroup boardGroup){
        this.volumes = boardGroup;
    }
    //
    public Album getAlbum() {
        return album;
    }
    public void setAlbum(Album album){
        this.album = album;
    }
    
    public Member getAuthor() {
        return author;
    }
    private void setAuthor(Member author) {
        this.author = author;
    }
    /**
     * 调用的前置检查条件为getAuthor为null,否则不会调用参数函数
     * @param memberFun 
     */
    public void copyMember(Function<Long, Optional<Member>> memberFun){
        if(null!=getAuthor()){
            return;
        }
        Optional<Member> tmp = super.isAnony()?Optional.of(Member.anonyMember(getAnonyMemberName())):memberFun.apply(super.getMemberId());
        tmp.ifPresent(m->{
            setAuthor(m);
            if(null!=getContent()){
                getContent().setMember(m);
            }
        });
    }
    //事件需要的
    public String getUserAgent() {
        return userAgent;
    }
    public void setUserAgent(String userAgent) {
        this.userAgent = userAgent;
    }
    //匿名加入的方法重写
    @Override
    public String getMemberNickname() {
        return super.isAnony()?getAnonyMemberName():super.getMemberNickname();
    }
    @Override
    public long getMemberId() {
        return super.isAnony()?0L:super.getMemberId();
    }
    //
    @Override
    public String getConnect() {
        return getId() + "-" + getBoardId() + "-" + getVolumesId();
    }
    
    @Override
    public Optional<TopicReplica> 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) {
            TopicReplica topic = new TopicReplica();
            topic.setVolumesId(Commons.stringToInteger(params[0], -1));
            return Optional.of(topic);
        }
        if (params.length == 2) {
            TopicReplica topic = new TopicReplica();
            topic.setBoardId(Commons.stringToLong(params[0], 0L));
            topic.setVolumesId(Commons.stringToInteger(params[1], -1));
            return Optional.of(topic);
        }
        if (params.length == 3) {
            TopicReplica topic = new TopicReplica();
            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();
    }
    
    public BoardReplica getLazyBoard() {
        if (getBoard() != null) {
            return getBoard();
        }
        BoardReplica b = new BoardReplica();
        b.setId(getBoardId());
        b.setVolumesId(getVolumesId());
        return b;
    }
    
    public static String generateConnectString(long topicId, long boardId, int boardGroupId){
        TopicReplica tr = new TopicReplica();
        tr.setId(topicId);
        tr.setBoardId(boardId);
        tr.setVolumesId(boardGroupId);
        
        return tr.getConnect();
    }
    private String getAnonyMemberName(){
        return String.format("Anony#%d", Commons.ipHashcode(super.getIpAddr()));
    }
    /**
     * 输出事件需要的Topic实例
     * @return
     */
    public Topic toEventPayload(){
        Topic et = new Topic();
        et.setId(this.getId());
        et.setTitle(this.getTitle());
        et.setMemberId(this.getMemberId());
        et.setMemberNickname(this.getMemberNickname());
        et.setBoardId(this.getBoardId());
        et.setVolumesId(this.getVolumesId());
        et.setEntryDateTime(this.getEntryDateTime());
        return et;
    }
}