package org.jim.server.command.handler;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.jim.common.ImConst;
import org.jim.common.ImPacket;
import org.jim.common.ImStatus;
import org.jim.common.packets.*;
import org.jim.server.model.ConversationRecord;
import org.jim.server.model.GroupConversationMiddle;
import org.tio.core.ChannelContext;
import org.jim.common.message.MessageHelper;
import org.jim.common.utils.ImKit;
import org.jim.common.utils.JsonKit;
import org.jim.server.command.AbstractCmdHandler;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 获取聊天消息命令处理器
 * @author WChao
 * @date 2018年4月10日 下午2:40:07
 */
public class MessageReqHandler extends AbstractCmdHandler {
	
	@Override
	public Command command() {
		
		return Command.COMMAND_GET_MESSAGE_REQ;
	}

	@Override
	public ImPacket handler(ImPacket packet, ChannelContext channelContext) throws Exception {
		RespBody resPacket = null;
		MessageReqBody messageReqBody = null;
		try{
			messageReqBody = JsonKit.toBean(packet.getBody(),MessageReqBody.class);
		}catch (Exception e) {
			//用户消息格式不正确
			return getMessageFailedPacket(channelContext);
		}
		//当前用户ID;
		String userId = messageReqBody.getUserId();
		//群组ID;
		String groupId = messageReqBody.getGroupId();
		//消息类型;
		int type = messageReqBody.getType();
		//如果用户ID为空或者type格式不正确或者群组id为空，获取消息失败;
		if( StringUtils.isEmpty(userId) || StringUtils.isEmpty(groupId) || (0 != type && 1 != type) ){
			return getMessageFailedPacket(channelContext);
		}
		if(type == 0){
			resPacket = new RespBody(Command.COMMAND_GET_MESSAGE_RESP,ImStatus.C10016);
		}else{
			resPacket = new RespBody(Command.COMMAND_GET_MESSAGE_RESP,ImStatus.C10018);
		}
		//群组ID不为空获取用户该群组消息;
		if(ImConst.ON.equals(imConfig.getIsStore())){
			return this.disposeRedisData(messageReqBody, channelContext, resPacket);
		}else{
			//从 数据库 中 获取 数据
			return this.disposeMysqlData(groupId,userId,channelContext,resPacket);
		}
	}

	/**
	 * 从数据库中获取数据
	 * @param groupId
 	 * @param userId
 	 * @param channelContext
 	 * @param resPacket
	 * @return {@link {@link ImPacket}}
	 * @author Darren
	 * @date 2020/2/19 17:01
	 */
	private ImPacket disposeMysqlData(
			String groupId, String userId, ChannelContext channelContext, RespBody resPacket
	){
		Map<String, List<ChatBody>> groups = new HashMap<>();
		groups.put(groupId,this.getChatBodyListByGroupId(groupId));
		UserMessageData messageData = new UserMessageData(userId);
		messageData.setGroups(groups);
		resPacket.setData(messageData);
		return ImKit.ConvertRespPacket(resPacket, channelContext);
	}

	/**
	 * 根据groupId 获取 chatBodyList
	 * @param groupId
	 * @return {@link {@link List< ChatBody>}}
	 * @author Darren
	 * @date 2020/2/19 17:11
	 */
	private List<ChatBody> getChatBodyListByGroupId(String groupId){
		List<ChatBody> chatBodyList = new ArrayList<>();
		List<GroupConversationMiddle> groupConversationMiddleList = GroupConversationMiddle.dao
				.find("SELECT * FROM sw_group_conversation_middle WHERE group_id = ? order by create_time ASC ", groupId);
		if(CollectionUtils.isNotEmpty(groupConversationMiddleList)){
			for (GroupConversationMiddle conversationMiddle : groupConversationMiddleList) {
				List<ConversationRecord> conversationRecords = ConversationRecord.dao
						.find(
								"SELECT * FROM sw_conversation_record WHERE conversation_id = ? order by create_time ASC "
								, conversationMiddle.getLong("conversation_id")
						);
				if(CollectionUtils.isNotEmpty(conversationRecords)){
					for (ConversationRecord conversationRecord : conversationRecords) {
						ChatBody chatBody = ChatBody.newBuilder().build();
						chatBody.setId(conversationRecord.getStr("chat_body_id"));
						chatBody.setCreateTime(conversationRecord.getTimestamp("create_time").getTime());
						chatBody.setFrom(conversationRecord.getStr("chat_body_from"));
						chatBody.setTo(conversationRecord.getStr("chat_body_to"));
						chatBody.setMsgType(conversationRecord.getInt("chat_body_msg_type"));
						chatBody.setGroup_id(groupId);
						chatBody.setContent(conversationRecord.getStr("content"));
						chatBody.setChatType(ChatType.CHAT_TYPE_PUBLIC.getNumber());
						Map<String, Object> map = new HashMap<>();
						map.put("type",conversationRecord.getStr("type"));
						chatBody.setExtras(new JSONObject(map));
						chatBodyList.add(chatBody);
					}
				}
			}
		}
		return chatBodyList;
	}

	/**
	 * 获取redis中的数据
 	 * @param messageReqBody
 	 * @param channelContext
 	 * @param resPacket
	 * @return {@link {@link ImPacket}}
	 * @author Darren
	 * @date 2020/2/19 15:24
	 */
	private ImPacket disposeRedisData(
			MessageReqBody messageReqBody, ChannelContext channelContext, RespBody resPacket
	){
		UserMessageData messageData = null;
		MessageHelper messageHelper = imConfig.getMessageHelper();
		//群组ID;
		String groupId = messageReqBody.getGroupId();
		//当前用户ID;
		String userId = messageReqBody.getUserId();
		//消息来源用户ID;
		String fromUserId = messageReqBody.getFromUserId();
		//消息区间开始时间;
		Double beginTime = messageReqBody.getBeginTime();
		//消息区间结束时间;
		Double endTime = messageReqBody.getEndTime();
		//分页偏移量;
		Integer offset = messageReqBody.getOffset();
		//分页数量;
		Integer count = messageReqBody.getCount();
		//消息类型;
		int type = messageReqBody.getType();
		if(!StringUtils.isEmpty(groupId)){
			//离线消息;
			if(0 == type){
				messageData = messageHelper.getGroupOfflineMessage(userId,groupId);
				//历史消息;
			}else if(1 == type){
				messageData = messageHelper.getGroupHistoryMessage(userId, groupId,beginTime,endTime,offset,count);
			}
		}else if(StringUtils.isEmpty(fromUserId)){
			//获取用户所有离线消息(好友+群组);
			if(0 == type){
				messageData = messageHelper.getFriendsOfflineMessage(userId);
			}else{
				return getMessageFailedPacket(channelContext);
			}
		}else{
			//获取与指定用户离线消息;
			if(0 == type){
				messageData = messageHelper.getFriendsOfflineMessage(userId, fromUserId);
				//获取与指定用户历史消息;
			}else if(1 == type){
				messageData = messageHelper.getFriendHistoryMessage(userId, fromUserId,beginTime,endTime,offset,count);
			}
		}
		resPacket.setData(messageData);
		return ImKit.ConvertRespPacket(resPacket, channelContext);
	}

	/**
	 * 获取用户消息失败响应包;
	 * @param channelContext
	 * @return
	 */
	public ImPacket getMessageFailedPacket(ChannelContext channelContext){
		RespBody resPacket = new RespBody(Command.COMMAND_GET_MESSAGE_RESP,ImStatus.C10015);
		return ImKit.ConvertRespPacket(resPacket, channelContext);
	}

}
