package com.apobates.forum.trident.controller;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.CacheControl;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.support.RequestContextUtils;
import com.apobates.forum.attention.core.AvatarImagePathConvertHandler;
import com.apobates.forum.attention.core.ImagePathCoverter;
import com.apobates.forum.attention.core.ImageStorePath;
import com.apobates.forum.core.api.ImageIOMeta;
import com.apobates.forum.core.api.TopicStatsCollect;
import com.apobates.forum.core.api.TopicStatsCollect.TopicStatsCollectBuilder;
import com.apobates.forum.core.api.service.TopicActionCollectionService;
import com.apobates.forum.event.elderly.ForumActionEnum;
import com.apobates.forum.event.elderly.MemberActionDescriptor;
import com.apobates.forum.trident.OnlineDescriptor;
import com.apobates.forum.trident.exception.ResourceNotFoundException;
import com.apobates.forum.trident.vo.MemberModel;
import com.apobates.forum.trident.controller.form.LoginForm;
import com.apobates.forum.trident.controller.form.RegisteForm;
import com.apobates.forum.member.MemberBaseProfile;
import com.apobates.forum.member.MemberProfileBean;
import com.apobates.forum.member.api.service.MemberLevelService;
import com.apobates.forum.member.api.service.MemberOnlineService;
import com.apobates.forum.member.api.service.MemberService;
import com.apobates.forum.member.entity.Member;
import com.apobates.forum.member.entity.MemberGroupEnum;
import com.apobates.forum.member.entity.MemberLevel;
import com.apobates.forum.member.entity.MemberOnline;
import com.apobates.forum.member.entity.MemberRoleEnum;
import com.apobates.forum.member.storage.OnlineMemberStorage;
import com.apobates.forum.member.storage.core.MemberSessionBean;
import com.apobates.forum.utils.CommonBean;
import com.apobates.forum.utils.Commons;
import com.apobates.forum.utils.DateTimeUtils;
import com.apobates.forum.utils.TipMessage;
import com.apobates.forum.utils.lang.EnumArchitecture;
import com.github.jscookie.javacookie.Cookies;
import org.apache.commons.io.IOUtils;
/**
 * 会员控制器
 * 
 * @author xiaofanku@live.cn
 * @since 20190306
 */
@Controller
@RequestMapping(value = "/member")
public class MemberController {
	@Autowired
	private ServletContext servletContext;
	@Autowired
	private MemberService memberService;
	@Autowired
	private TopicActionCollectionService topicActionCollectionService;
	@Autowired
	private MemberOnlineService memberOnlineService;
	@Autowired
	private OnlineMemberStorage onlineMemberStorage;
	@Autowired
	private MemberLevelService memberLevelService;
	@Autowired
	private ImageIOMeta imageIOConfig;
	@Value("${site.defat.avtar}")
	private String avatarDefaultDirect;
	@Value("${site.pageSize}")
	private int pageSize;
	private final static Logger logger = LoggerFactory.getLogger(MemberController.class);

	// 会员主页
	@GetMapping(path="/{id}.xhtml")
	@OnlineDescriptor(action=ForumActionEnum.COMMON_VISIT)
	public String home(
			@PathVariable("id") long memberId, 
			@RequestParam(value = "token", required = false, defaultValue = "0")String token, 
			MemberSessionBean mbean, 
			HttpServletRequest request, 
			Model model) {
		Member m = memberService.get(memberId).orElseThrow(()->new ResourceNotFoundException("目标丢失或暂时无法访问"));
		model.addAttribute("mine", (memberId == mbean.getMid()));
		model.addAttribute("token", token);
		//
		Map<String, String> data = new HashMap<>(getStats(memberId).toMap());
		// 活跃记录
		Optional<MemberOnline> mos = memberOnlineService.get(memberId);
		if (mos.isPresent()) {
			data.put("activeDateTime", DateTimeUtils.formatClock(mos.get().getActiveDateTime()));
		} else {
			data.put("activeDateTime", "-");
		}
		model.addAttribute("member", MemberBaseProfile.init(m).toMergeMap(data));
		return "default/member/index";
	}
	
	private TopicStatsCollect getStats(long memberId) {
		TopicStatsCollectBuilder tscb = new TopicStatsCollectBuilder(memberId);
		Map<ForumActionEnum, Long> statsActions = topicActionCollectionService.statsMemberAction(memberId, Arrays.asList(ForumActionEnum.TOPIC_PUBLISH, ForumActionEnum.POSTS_REPLY, ForumActionEnum.TOPIC_LIKED, ForumActionEnum.TOPIC_FAVORITE));
		try {
			Long ts = statsActions.get(ForumActionEnum.TOPIC_PUBLISH);
			tscb.threads(Commons.optionalOrZero(ts));
		} catch (Exception e) {
		}
		try {
			Long rs = statsActions.get(ForumActionEnum.POSTS_REPLY);
			tscb.replies(Commons.optionalOrZero(rs));
		} catch (Exception e) {
		}
		//
		try {
			Long tls = statsActions.get(ForumActionEnum.TOPIC_LIKED);
			tscb.threadsLikes(Commons.optionalOrZero(tls));
		} catch (Exception e) {
		}
		try {
			Long fls = statsActions.get(ForumActionEnum.TOPIC_FAVORITE);
			tscb.threadsFavorites(Commons.optionalOrZero(fls));
		} catch (Exception e) {
		}
		return tscb.build();
	}
	// 会员面板(页面顶部的)
	@GetMapping(path = "/panel", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public String getMemberProfile(MemberSessionBean mbean, HttpServletRequest request, Model model) {
		try {
			MemberSessionBean tmp = mbean.clone(decodeDefaultAvatarURL(Optional.of(mbean.getAvatar()), onlineMemberStorage.getMetaConfig().getSite()+"/"+avatarDefaultDirect));
			return tmp.toJson();
		} catch (IOException e) {
			if (logger.isDebugEnabled()) {
				logger.debug("convert member avatar fail");
			}
		}
		
		return "{}";
	}

	// 查看任意会员头像
	@GetMapping(path = "/avatar/{id}.png", produces = MediaType.IMAGE_PNG_VALUE)
	public ResponseEntity<byte[]> getMemberAvatar(
			@PathVariable("id") long memberId, 
			HttpServletResponse response, 
			Model model) {
		Optional<String> rav = memberService.getMemberAvatar(memberId);
		try {
			String avatarFilePath = "/" + avatarDefaultDirect + AvatarImagePathConvertHandler.getDefaultAvtarFilePath(rav.orElse("/empty.png"));
			InputStream in = servletContext.getResourceAsStream(avatarFilePath);
			byte[] avtarBytes = IOUtils.toByteArray(in);
			final HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.IMAGE_PNG);
			headers.setContentLength(avtarBytes.length);
			return new ResponseEntity<byte[]>(avtarBytes, headers, HttpStatus.CREATED);
		} catch (IOException e) {
			response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
			return null;
		}
	}
	// 会员等级图标
	@GetMapping(path = "/level/ico/{id}.png", produces = MediaType.IMAGE_PNG_VALUE)
	public ResponseEntity<byte[]> getMemberLevelIco(
			@PathVariable("id") int memberLevelId, 
			HttpServletResponse response, 
			Model model) {
		MemberLevel level = memberLevelService.get(memberLevelId).orElse(null);
		if(null == level){
			response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
			return null;
		}
		try {
			String levelIcoURL = new ImagePathCoverter(level.getImageAddr())
								.decodeUploadImageFilePath(imageIOConfig.getImageBucketDomain(), imageIOConfig.getUploadImageDirectName())
								.orElse("/board/ico/default_icon.png");
			InputStream in = new URL(levelIcoURL).openStream();
			byte[] avtarBytes = IOUtils.toByteArray(in);

			final HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.IMAGE_PNG);
			headers.setCacheControl(CacheControl.noCache().getHeaderValue());
			return new ResponseEntity<byte[]>(avtarBytes, headers, HttpStatus.CREATED);
		} catch (IOException e) {
			response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
			return null;
		}
	}
	
	// 快速登录
	@PostMapping(path = "/login/quick", produces = "application/json;charset=UTF-8")
	@ResponseBody
	@OnlineDescriptor(action=ForumActionEnum.MEMBER_LOGIN, isAjax=true)
	public String quickLoginAction(
			@RequestParam("names") String names, 
			@RequestParam("password") String password, 
			@RequestParam(value = "token", required = false, defaultValue = "0")String token, 
			HttpServletRequest request, 
			HttpServletResponse response, 
			Model model) {
		MemberActionDescriptor mad = MemberActionDescriptor.getInstance(request, token);
		Optional<Member> rm = memberService.signIn(names.trim(), password.trim(), mad);
		//
		if (!rm.isPresent()) {
			return TipMessage.ofError("会员不存在或密码错误").toJsonString();
		}
		MemberSessionBean mbean = new MemberSessionBean(rm.get(), mad.getIpAddr());
		onlineMemberStorage.store(mbean, request, response);
		return mbean.toJson(); 
	}
	
	// 登录
	@GetMapping(path = "/login")
	@OnlineDescriptor(action=ForumActionEnum.MEMBER_LOGIN)
	public String loginForm(
			@RequestParam(value = "from", required = false, defaultValue = "") String fromPath, 
			@RequestParam(value = "token", required = false, defaultValue = "0")String token, 
			MemberSessionBean mbean, 
			HttpServletRequest request, 
			Model model) {
		if (mbean.isOnline()) {
			return "redirect:/";
		}
		LoginForm form = new LoginForm();
		String A = Commons.isNotBlank(fromPath) ? fromPath : Commons.getNativeURL(request.getHeader("referer"), onlineMemberStorage.getMetaConfig().getSite(), "/");
		form.setRedirect(A);
		form.setTries(1);
		form.setToken(token);
		model.addAttribute("form", form);
		return "default/member/login";
	}
	@PostMapping(path="/login")
	@OnlineDescriptor(action=ForumActionEnum.MEMBER_LOGIN)
	public String loginAction(
			@ModelAttribute("form") LoginForm form, 
			HttpServletRequest request, 
			HttpServletResponse response, 
			Model model) {
		MemberActionDescriptor mad = MemberActionDescriptor.getInstance(request, form.getToken());
		String errMsg = null;Member m=null;
		try{
			Optional<Member> rm = memberService.signIn(form.getNames(), form.getPswd(), mad);
			if (!rm.isPresent()) {
				errMsg = "会员不存在或密码错误";
			}else{
				m=rm.get();
			}
		}catch(IllegalStateException e){
			errMsg = e.getMessage();
		}
		if (null == m) {
			form.setTries(form.getTries() + 1);
			model.addAttribute("form", form);
			//
			model.addAttribute("errors", errMsg);
			return "default/member/login";
		}
		MemberSessionBean mbean = new MemberSessionBean(m, mad.getIpAddr());
		onlineMemberStorage.store(mbean, request, response);
		// ----------------------------------------清除客户端缓存的cookie标记,重新拉取@20200502
		if(Commons.isNotBlank(form.getTrace())){
			emptyTraceForCookie(form.getTrace(), "login", request, response);
		}
		if(Commons.isNotBlank(form.getRedirect())){
			return "redirect:" + (forbidRTLoginDirectURL(form.getRedirect())?"/":form.getRedirect()); //保证地址是内部可跳转
		}
		return "redirect:/member/" + mbean.getMid() + ".xhtml";
	}
	//注册->提示->登录禁止跳转的地址
	private boolean forbidRTLoginDirectURL(String jumpUrl){
		return Arrays.asList("/member/register", "/member/register/success.xhtml", "/member/login").contains(jumpUrl);
	}
	// 注册
	@GetMapping(path="/register")
	@OnlineDescriptor(action=ForumActionEnum.MEMBER_REGISTER)
	public String registeForm(
			@RequestParam(value = "invite", required = false, defaultValue = "")String inviteCode, 
			@RequestParam(value = "token", required = false, defaultValue = "0")String token, 
			MemberSessionBean mbean, 
			HttpServletRequest request, 
			Model model) {
		// --------------------------------------------------
		if (mbean.isOnline()) { // (R->T->L)(firefox: /member/register)
			return "redirect:/";
		}
		// 配合:MemberInviteCodeInterceptorAdapter,不然会丢失上次输入的值
		Map<String, ?> inputFlashMap = RequestContextUtils.getInputFlashMap(request);
		if (inputFlashMap == null || !inputFlashMap.containsKey("form")) {
			RegisteForm form = new RegisteForm();
			form.setToken(token);
			model.addAttribute("form", form);
		}
		return "default/member/register";
	}
	@PostMapping(path="/register")
	@OnlineDescriptor(action=ForumActionEnum.MEMBER_REGISTER)
	public String registeAction(
			@ModelAttribute("form") RegisteForm form, 
			HttpServletRequest request, 
			HttpServletResponse response,
			Model model) {
		String mnames = Commons.getAlphaNumberCharacter(form.getNames());
		if (mnames.length() < 5 || mnames.length() > 20) {
			model.addAttribute("errors", "帐号可用长度小于5或大于20");
			model.addAttribute("form", form);
			return "default/member/register";
		}
		String mnick = Commons.chineseStringLength(form.getNickname()) < 5 ? "Member#" + Commons.randomNumeric(4) : form.getNickname();
		try {
			if (memberService.signUp(
					mnames, 
					form.getPswdConfirm(),
					request.getParameter(Commons.optional(() -> request.getSession().getAttribute("ICInputKey"), "-")),
					mnick, 
					MemberActionDescriptor.getInstance(request, form.getToken()))
					.isPresent()) {
				return "redirect:/member/register/success.xhtml";
			}
		} catch (IllegalArgumentException | IllegalStateException e) {
			if (logger.isDebugEnabled()) {
				logger.debug(e.getMessage(), e);
			}
		}
		form.setNickname(mnick);
		form.setNames(mnames);
		model.addAttribute("form", form);
		model.addAttribute("errors", "会员注册失败");
		return "default/member/register";
	}
	//配合:Bootstrap validator使用@see:https://github.com/1000hz/bootstrap-validator@BS3
	//配合:parsley.js使用@see:http://parsleyjs.org/@BS4
	//检查会员帐号是否可用
	@GetMapping(path = "/detection/unique")
	public ResponseEntity<String> checkMemberNames(
			@RequestParam("names")String names, 
			HttpServletRequest request, 
			Model model){
		String tipMessage; boolean symbol = false;
		Optional<Boolean> result = memberService.checkNamesUnique(names);
		if(result.isPresent()){
			tipMessage = result.get()?"可以使用":"未知的错误";
			symbol = true;
		}else{
			tipMessage = "会员帐号唯一性检测失败";
		}
		//
		HttpHeaders responseHeaders = new HttpHeaders();
		responseHeaders.set("Content-Type", "text/plain; charset=UTF-8"); //Content-Type: text/plain;charset=ISO-8859-1
		HttpStatus hs = symbol?HttpStatus.OK:HttpStatus.BAD_REQUEST;
		return new ResponseEntity<>(tipMessage, responseHeaders, hs);
	}
	// 配合:Bootstrap
	// validator使用@see:https://github.com/1000hz/bootstrap-validator@BS3
	// 配合:parsley.js使用@see:http://parsleyjs.org/@BS4
	// 检查注册邀请码是否可用
	@GetMapping(path = "/detection/invite")
	public ResponseEntity<String> checkMemberInviteCode(@RequestParam("code") String inviteCode, HttpServletRequest request, Model model) {
		String tipMessage = "验证码不可用";
		boolean symbol = false;
		//
		Map<String, String> result = memberService.getActiveInviteCode(inviteCode);
		if (!result.get("id").equals("0")) {
			tipMessage = "可以使用";
			symbol = true;
		}
		HttpHeaders responseHeaders = new HttpHeaders();
		responseHeaders.set("Content-Type", "text/plain; charset=UTF-8"); // Content-Type:text/plain;charset=ISO-8859-1
		HttpStatus hs = symbol ? HttpStatus.OK : HttpStatus.BAD_REQUEST;
		return new ResponseEntity<>(tipMessage, responseHeaders, hs);
	}
	//校验uid时的
	@GetMapping(path = "/detection/uid")
	@ResponseBody
	public TipMessage checkMemberUID(
			@RequestParam("value")String uidString, 
			MemberSessionBean mbean, 
			HttpServletRequest request, 
			Model model){
		long memberId = 0L;
		try{
			memberId = Long.valueOf(uidString.substring(1));
		}catch(Exception e){
			return TipMessage.ofError("非法的会员");
		}
		if(memberId <= 0){
			return TipMessage.ofError("会员不接受消息");
		}
		Member m = memberService.get(memberId).orElse(null);
		if(null == m || m.getId() == mbean.getMid()){
			return TipMessage.ofError("会员不存在");
		}
		return TipMessage.ofSuccess(m.getNickname());
	}
	// 退出系统
	@GetMapping(path="/offline.xhtml")
	public String signout(
			@RequestParam(value = "token", required = false, defaultValue = "0")String token, 
			@RequestParam(value = "trace", required = false, defaultValue = "")String cookieTraceKey, 
			MemberSessionBean mbean, 
			HttpServletRequest request, 
			HttpServletResponse response, 
			HttpSession session, 
			Model model) {
		if (mbean.isOnline()) {
			memberService.signOut(mbean.getNames(), mbean.toMember(), MemberActionDescriptor.getInstance(request, token));
			// ----------------------------------------移除Cookie
			onlineMemberStorage.delete(request, response);
			// ----------------------------------------清除客户端缓存的cookie标记,重新拉取@20200502
			if(Commons.isNotBlank(cookieTraceKey)){
				emptyTraceForCookie(cookieTraceKey, "offline", request, response);
			}
		}
		return "default/member/logout";
	}

	@GetMapping(path="/register/success.xhtml")
	public String registeSuccess(MemberSessionBean mbean, HttpServletRequest request, Model model) throws IllegalAccessException {
		//来源页判断 http Referer: site.domain{http://center.test.com}/member/register
		String reqRef = request.getHeader("referer");
		if(null == reqRef || !reqRef.equals(onlineMemberStorage.getMetaConfig().getSite()+"/member/register")){
			throw new IllegalAccessException("非法的请求路径");
		}
		if(mbean.isOnline()){ 
			return "redirect:/";
		}
		return "default/member/success";
	}

	@GetMapping(path="/register/licenses.xhtml")
	public String registeLicenses() {
		return "default/member/licenses";
	}

	// 会员统计(话题内容页)[DEP]
	@GetMapping(path = "/profile/list.json", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public List<MemberProfileBean> getMembereProfiles(@RequestParam("ids") String memberIdString, HttpServletRequest request, Model model){
		List<Long> memberIdList = Commons.toLongList(memberIdString);
		
		if(memberIdList.isEmpty()){
			return Collections.emptyList();
		}
		//
		Map<Long, EnumMap<ForumActionEnum, Long>> rawdata = topicActionCollectionService.groupMemberTopicAction(memberIdList); 
		if(rawdata == null || rawdata.isEmpty()) {
			return Collections.emptyList();
		}
		return memberService.getMemberProfileBeanes(memberIdList, rawdata);
	}
	
	// 会员菜单(话题内容页)
	@GetMapping(path = "/profile.json", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public MemberProfileBean getMembereProfile(
			@RequestParam("id") long memberId, 
			HttpServletRequest request, 
			Model model){
		EnumMap<ForumActionEnum, Long> rawdata = topicActionCollectionService.groupMemberTopicAction(memberId);
		return memberService.getMemberProfileBean(memberId, rawdata).orElse(MemberProfileBean.guest());
	}
	
	//版块首页(/board/home)的社区标兵
	@GetMapping(path = "/model/json", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public List<MemberModel> getTopicMemberModel(HttpServletRequest request, Model model){
		Map<Long, Map<String, Long>> rs = topicActionCollectionService.orderMemberTopices(10);
		Function<Entry<Long, Map<String, Long>>, MemberModel> coverMapper = entry -> {
			long mid = entry.getKey();
			return entry.getValue().entrySet().stream().map(tmp -> new MemberModel(mid, tmp.getKey(), tmp.getValue())).findFirst().get();
		};
		Stream<MemberModel> data = rs.entrySet().stream().map(coverMapper);
		return data.sorted(Comparator.comparing(MemberModel::getValue).reversed()).collect(Collectors.toList());
	}
	
	//话题|版块配置中允许的会员组
	@GetMapping(path="/group/json", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public List<CommonBean> getAllowMemberGroup(){
		Map<Integer,String> memberGroupData = EnumArchitecture.getInstance(MemberGroupEnum.class);
		return memberGroupData.entrySet().stream().filter(r -> r.getKey() >= 0 && r.getKey() < 3).map(r -> new CommonBean(r.getKey(), r.getValue())).collect(Collectors.toList());
	}
	
	//话题|版块配置中允许的会员角色
	@GetMapping(path="/role/json", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public List<CommonBean> getAllowMemberRole(){
		Map<Integer,String> memberRoleData = EnumArchitecture.getInstance(MemberRoleEnum.class);
		return memberRoleData.entrySet().stream().map(r -> new CommonBean(r.getKey(), r.getValue())).collect(Collectors.toList());
	}
	
	//[版块列表]底部的会员统计汇总
	@GetMapping(path = "/stats/collect", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public Map<String,String> getMemberStatsCollect(HttpServletRequest request, Model model){
		Map<String,String> stats = new HashMap<>();
		try{
			stats.put("members", memberService.count()+""); //注册人数
		}catch(NullPointerException e){
			stats.put("members", "0");
		}
		try{
			String jsonString = memberService.getRecent(1).map(m -> new CommonBean(m.getId(), m.getNickname())).map(CommonBean::toJson).findAny().orElse("{}");
			stats.put("recentMember", jsonString); //最近注册的会员是谁?
		}catch(NullPointerException e){
			stats.put("recentMember", "{}");
		}
		
		long onlines = 0L;
		try{
			LocalDateTime finish = LocalDateTime.now();
			LocalDateTime start = DateTimeUtils.beforeMinuteForDate(finish, 30);
			onlines = memberOnlineService.count(start, finish); //这里不包含游客
		}catch(Exception e){}
		stats.put("onlines", onlines+""); //在线的总人数
		
		return stats;
	}

	// 快速登录的表单
	@GetMapping(path="/login/form")
	public String getQuickLoginForm(
			@RequestParam(value = "token", required = false, defaultValue = "0")String token, 
			MemberSessionBean mbean, 
			HttpServletRequest request, 
			Model model){
		//---------------------------------------------是否来源自本站
		String requestRefString = request.getHeader("referer");
		if (null==requestRefString || !requestRefString.startsWith(onlineMemberStorage.getMetaConfig().getSite())) { // 只允许本站连接
			return "default/common/illegal_embed";
		}
		//---------------------------------------------
		if(mbean.isOnline()){
			Map<String,String> extMap = new HashMap<>();
			extMap.put("status", mbean.getStatus().getTitle());
			model.addAttribute("member", MemberBaseProfile.init(mbean.toMember()).toMergeMap(extMap));
			return "default/member/member_info_embedded";
		}
		model.addAttribute("token", token);
		return "default/member/login_embedded";
	}
	/**
	 * 解码会员头像|头像是本地存储
	 * 
	 * @param avatarURI              DB中保存的编码后的头像地址,例:avtar://defat[|local|remot]/目录名/文件名
	 * @param domainDefaultAvatarURI 站内默认头像的访问地址前缀
	 * @return
	 * @throws MalformedURLException
	 */
	private URL decodeDefaultAvatarURL(Optional<String> avatarURI, final String domainDefaultAvatarURI) throws MalformedURLException {
		String avURI = avatarURI.orElse(Member.GUEST_AVATAR);
		// 转换参数avatarURI
		Optional<String> data = new ImagePathCoverter(avURI).decodeAvatarPath(new ImageStorePath() {
			@Override
			public String getDefaultImagePath() {
				return domainDefaultAvatarURI;
			}

			@Override
			public String getLocalImagePath() {
				return null;
			}

			@Override
			public String getRemoteImagePath() {
				return null;
			}
		});
		return new URL(data.orElse(domainDefaultAvatarURI + "empty.png"));
	}
	/**
	 * 清除客户端缓存的cookie标记,重新拉取一次@20200502<br/>
	 * 需要js-cookie的服务器端依赖<br/>
	 * [有重复]com.apobates.forum.trident.controller.admin.HomeController.emptyTraceForCookie
	 * {@link https://github.com/js-cookie/java-cookie}
	 * {@link https://github.com/js-cookie/js-cookie/blob/master/SERVER_SIDE.md}
	 * @param cookieKey js-cookie设置的cookie key, 客户端缓存的cookie标记
	 * @param source    来自哪个方法
	 * @param request   http请求对象
	 * @param response  http响应对象
	 */
	private void emptyTraceForCookie(String cookieKey, String source, HttpServletRequest request, HttpServletResponse response){
		logger.info(String.format("[HMP][%s]current destroy cookie by key:%s", source, cookieKey));
		Cookies cookies = Cookies.initFromServlet(request, response);
		cookies.remove(cookieKey);
	}
}
