package org.jim.server.command.handler;

import org.apache.commons.collections4.CollectionUtils;
import org.jim.common.ImConst;
import org.jim.common.ImAio;
import org.jim.common.ImPacket;
import org.jim.common.ImSessionContext;
import org.jim.common.ImStatus;
import org.jim.common.cache.redis.JedisTemplate;
import org.jim.common.message.MessageHelper;
import org.jim.common.packets.Command;
import org.jim.common.packets.Group;
import org.jim.common.packets.LoginReqBody;
import org.jim.common.packets.LoginRespBody;
import org.jim.common.packets.User;
import org.jim.common.protocol.IProtocol;
import org.jim.common.utils.ImKit;
import org.jim.common.utils.JsonKit;
import org.jim.server.command.AbstractCmdHandler;
import org.jim.server.command.CommandManager;
import org.jim.server.command.handler.processor.login.LoginCmdProcessor;
import org.jim.server.enums.VisitTypeEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tio.core.Aio;
import org.tio.core.ChannelContext;
import org.tio.utils.lock.SetWithLock;

import java.util.List;
import java.util.Set;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;

/**
 * 登录消息命令处理器
 * @author WChao
 * @date 2018年4月10日 下午2:40:07
 */
public class LoginReqHandler extends AbstractCmdHandler {
	private static Logger log = LoggerFactory.getLogger(LoginReqHandler.class);

	private static JedisTemplate jedisTemplate = null;

	static {
		try {
			jedisTemplate = JedisTemplate.me();
		} catch (Exception e) {
			log.info("JedisTemplate初始化失败!");
			e.printStackTrace();
		}
	}

	@Override
	public ImPacket handler(ImPacket packet, ChannelContext channelContext) throws Exception {
		if (packet.getBody() == null) {
			Aio.remove(channelContext, "body is null");
			return null;
		}
		List<LoginCmdProcessor> loginProcessors = this.getProcessor(channelContext, LoginCmdProcessor.class);
		if(CollectionUtils.isEmpty(loginProcessors)){
			log.info("登录失败,没有登录命令业务处理器!");
			Aio.remove(channelContext, "no login serviceHandler processor!");
			return null;
		}
		LoginCmdProcessor loginServiceHandler = loginProcessors.get(0);
		ImSessionContext imSessionContext = (ImSessionContext)channelContext.getAttribute();
		LoginReqBody loginReqBody = JsonKit.toBean(packet.getBody(),LoginReqBody.class);
		
		LoginRespBody loginRespBody = loginServiceHandler.doLogin(loginReqBody,channelContext);
		if (loginRespBody == null || loginRespBody.getUser() == null) {
			log.info("登录失败, token不正确");
			if(loginRespBody == null){
				loginRespBody = new LoginRespBody(Command.COMMAND_LOGIN_RESP, ImStatus.C10008);
			}
			loginRespBody.clear();
			ImPacket loginRespPacket = new ImPacket(Command.COMMAND_LOGIN_RESP, loginRespBody.toByte());
			ImAio.bSend(channelContext,loginRespPacket);
			ImAio.remove(channelContext, "loginName and token is incorrect");
			return null;
		}
		User user = loginRespBody.getUser();
		Boolean noOnlineService = user.getExtras().getBoolean("noOnlineService");
		if(noOnlineService != null && noOnlineService){
			//当前平台下 部门下没有 在线客服
			log.info("当前平台下 部门下没有 在线客服");
			loginRespBody.clear();
			ImPacket loginRespPacket = new ImPacket(Command.COMMAND_LOGIN_RESP, loginRespBody.toByte());
			ImAio.bSend(channelContext,loginRespPacket);
			ImAio.remove(channelContext, "current department's online service account is zero,please wait!");
			return null;
		}
		String userId = user.getId();
		IProtocol protocol = ImKit.protocol(null, channelContext);
		String terminal = protocol == null ? "" : protocol.name();
		user.setTerminal(terminal);
		imSessionContext.getClient().setUser(user);
		ImAio.bindUser(channelContext,userId,imConfig.getMessageHelper().getBindListener());
		//初始化绑定或者解绑群组;
		bindUnbindGroup(channelContext, user, user.getGroups());
		//判断当前用户 是否具有 查看所有客服权限 如果有 绑定群组
		hasViewAllServiceAccountAuthority(channelContext,user);
		loginServiceHandler.onSuccess(channelContext);
		loginRespBody.clear();
		ImPacket loginRespPacket = new ImPacket(Command.COMMAND_LOGIN_RESP, loginRespBody.toByte());
		return loginRespPacket;
	}

	/**
	 * 绑定群组为具有查看全部客服权限的 客服
	 * @param
	 * @return {@link }
	 * @author Darren
	 * @date 2020/2/4 19:32
	 */
	public void bindGroupForViewAllServiceAccountAuthority(User user, Group group){
		if( null != group ){
			ImPacket groupPacket = new ImPacket(Command.COMMAND_JOIN_GROUP_REQ,JsonKit.toJsonBytes(group));
			//获取 具有 权限的 客服容器
			String adminContainerKey = user.getExtras().getString("companyId")
					+ ImConst.SEPARATOR + user.getExtras().getString("departmentId")
					+ ImConst.SEPARATOR + ImConst.ADMIN ;
			// list 中存放的是 具有权限的 客服 userId ( == serviceAccountRoleDepartmentId)
			List<String> adminContainer = jedisTemplate.listGetAll(adminContainerKey);
			for(String serviceAccountRoleDepartmentId : adminContainer){
				//获取
				SetWithLock<ChannelContext> channelContexts = ImAio.getChannelContextsByUserId(serviceAccountRoleDepartmentId);
				//获取读锁
				ReadLock readLock = channelContexts.getLock().readLock();
				//加锁
				readLock.lock();
				try {
					Set<ChannelContext> channels = channelContexts.getObj();
					for (ChannelContext channelContext : channels) {
						//判断 通道 是否已经加入了 群组
						if( !Aio.isInGroup(group.getGroup_id(),channelContext) ){
							//该通道未加入该群组则 加入
							//获取加入群组 处理器
							JoinGroupReqHandler joinGroupReqHandler = CommandManager.getCommand(Command.COMMAND_JOIN_GROUP_REQ, JoinGroupReqHandler.class);
							joinGroupReqHandler.bindGroup(groupPacket, channelContext);
						}
					}
				} catch (Exception e) {
					log.error(e.toString(),e);
				}finally {
					//解锁
					readLock.unlock();
				}
			}
		}
	}

	/***
	 * 判断当前用户 是否具有 查看所有客服权限
	 * @param
	 * @return {@link }
	 * @author Darren
	 * @date 2020/2/3 20:08
	 */
	public void hasViewAllServiceAccountAuthority(ChannelContext channelContext , User user) throws Exception {
		if( VisitTypeEnum.SERVICEACCOUNT.getKey().equals(user.getVisitType()) ){
			if(Boolean.valueOf(user.getExtras().getString("hasViewAllServiceAccount"))){
				bindUnbindGroup(channelContext, user, user.getViewAllGroups());
			}
		}
	}

	/**
	 * 初始化绑定或者解绑群组;
	 */
	public void bindUnbindGroup(ChannelContext channelContext ,  User user, List<Group> groups)throws Exception{
		String userId = user.getId();
		if( groups != null){
			//判断是否开启持久化
			boolean isStore = ImConst.ON.equals(imConfig.getIsStore());
			MessageHelper messageHelper = null;
			List<String> groupIds = null;
			if(isStore){
				//获取 用于持久化 的 MesageHelper
				messageHelper = imConfig.getMessageHelper();
				//获取用户拥有的群组;
				groupIds = messageHelper.getGroups(userId);
			}
			//绑定群组
			for(Group group : groups){
				if(isStore && groupIds != null){
					groupIds.remove(group.getGroup_id());
				}
				ImPacket groupPacket = new ImPacket(Command.COMMAND_JOIN_GROUP_REQ,JsonKit.toJsonBytes(group));
				try {
					JoinGroupReqHandler joinGroupReqHandler = CommandManager.getCommand(Command.COMMAND_JOIN_GROUP_REQ, JoinGroupReqHandler.class);
					joinGroupReqHandler.bindGroup(groupPacket, channelContext);
				} catch (Exception e) {
					log.error(e.toString(),e);
				}
				//绑定群组为具有查看全部客服权限的 客服
				this.bindGroupForViewAllServiceAccountAuthority(user, group);
			}
			if(isStore && groupIds != null){
				for(String groupId : groupIds){
					messageHelper.getBindListener().onAfterGroupUnbind(channelContext, groupId);
				}
			}
		}
	}
	@Override
	public Command command() {
		return Command.COMMAND_LOGIN_REQ;
	}
}
