package com.apobates.forum.member;

import com.apobates.forum.member.entity.Member;
import com.apobates.forum.member.entity.MemberGroupEnum;
import com.apobates.forum.member.entity.MemberRoleEnum;
import com.apobates.forum.utils.Commons;
import java.io.Serializable;
import java.util.EnumMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

/**
 * 会员实体中的公用信息
 *
 * @author xiaofanku
 * @since 20200517
 */
public class MemberBaseProfile implements Serializable {
    private static final long serialVersionUID = 1L;
    //会员ID
    private final long id;
    //会员名称
    private final String nickname;
    //组名称
    private final String groupName; //中文名
    //角色名称
    private final String roleName;
    private final String label; //英文名
    //签名
    private final String signature;
    
    public MemberBaseProfile(
            long id,
            String nickname,
            MemberGroupEnum memberGroup,
            MemberRoleEnum memberRole,
            String signature) {
        super();
        this.id = id;
        this.nickname = nickname;
        this.groupName = memberGroup.getTitle();
        this.roleName = memberRole.getTitle();
        this.label = getStyle(memberGroup, memberRole);
        this.signature = signature;
    }
    public static MemberBaseProfile init(Member member) {
        return new MemberBaseProfile(
                member.getId(),
                member.getNickname(),
                member.getMgroup(),
                member.getMrole(),
                member.getSignature());
    }
    public long getId() {
        return id;
    }
    
    public String getNickname() {
        return nickname;
    }
    
    public String getGroupName() {
        return groupName;
    }
    
    public String getSignature() {
        return signature;
    }
    
    public String getRoleName() {
        return roleName;
    }
    
    public String getLabel() {
        return label;
    }
    
    /**
     * 返回一个不可变的map,不可以在结果基础上put
     * 
     * @return 
     */
    public Map<String, String> toMap() {
        return Map.ofEntries(Map.entry("id", getId() + ""), Map.entry("nickname", getNickname()), Map.entry("groupNames", getGroupName()), Map.entry("roleNames", getRoleName()), Map.entry("style", getLabel()), Map.entry("signature", getSignature()));
    }
    
    /**
     * 若extInfoMap中的key与toMap的key冲突,以toMap为准
     * 
     * @param extInfoMap 扩展的会员信息
     * @return 
     */
    public Map<String, String> toMergeMap(Map<String, String> extInfoMap) {
        return Commons.mergeMap(toMap(), extInfoMap, (oldValue, newValue)-> oldValue);
    }
    /**
     * 返回会员的色值样式
     * 
     * @param member 若参数为null返回空字符串
     * @return 
     */
    public static String getStyle(Member member) {
        return Optional.ofNullable(member).map((Member m)->MemberStyle.get(m.getMrole(), m.getMgroup())).orElse("");
    }
    /**
     * 返回会员的色值样式
     * 
     * @param mg 会员的组枚举
     * @param mr 会员的角色枚举
     * @return 
     */
    public static String getStyle(MemberGroupEnum mg, MemberRoleEnum mr) {
        return MemberStyle.get(mr, mg);
    }
    private static class MemberStyle {
        private final static EnumMap<MemberRoleEnum, String> ROLE_STYLE = new EnumMap<>(MemberRoleEnum.class);
        private final static EnumMap<MemberGroupEnum, String> GROUP_STYLE = new EnumMap<>(MemberGroupEnum.class);
        
        static {
            ROLE_STYLE.put(MemberRoleEnum.BM, "moderator");
            ROLE_STYLE.put(MemberRoleEnum.MASTER, "master");
            ROLE_STYLE.put(MemberRoleEnum.ADMIN, "admin");
            //
            GROUP_STYLE.put(MemberGroupEnum.CARD, "general");
            GROUP_STYLE.put(MemberGroupEnum.VIP, "vip");
            GROUP_STYLE.put(MemberGroupEnum.GUEST, "guest");
            GROUP_STYLE.put(MemberGroupEnum.SPIDER, "spider");
            GROUP_STYLE.put(MemberGroupEnum.ROBOT, "robot");
            GROUP_STYLE.put(MemberGroupEnum.LEADER, "manager");
        }
        //允许参数为null吗?
        public static String get(MemberRoleEnum mrole, MemberGroupEnum mgroup) {
            Objects.requireNonNull(mrole);
            Objects.requireNonNull(mgroup);
            return Optional.ofNullable(ROLE_STYLE.get(mrole)).or(()-> Optional.ofNullable(GROUP_STYLE.get(mgroup))).orElse("");
        }
    }
}