package com.pingpang.service.impl;

import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.dubbo.config.annotation.DubboService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.pingpang.dao.UserDao;
import com.pingpang.redis.RedisPre;
import com.pingpang.redis.service.RedisService;
import com.pingpang.service.UserService;
import com.pingpang.util.StringUtil;
import com.pingpang.websocketchat.ChartUser;
import com.pingpang.websocketchat.Message;

@Service
@Transactional
@DubboService
public class UserServiceImpl implements UserService{
   
	// 日志操作
    protected Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);
	
   @Autowired
   private UserDao userDao;
   
   /**
    * redis
    */
   @Autowired
   private RedisService redisService;
   
   /**
    * 更新map的某个字段
    * @param key
    * @param mapKey
    * @param value
    */
   public void addHashMap(String key,String mapKey,Object value) {
	   redisService.addHashMap(key, mapKey, value);
   }
   
   /**
    * 保存用户信息到hash表中
    * @param user
    * @return
    */
   public boolean addUserMap(ChartUser cu) {
	   //注销用户不用加载
	   if(null==cu || "-1".equals(cu.getUserStatus())) {
		   return false;
	   }
	   Map<String,Object> userMap=(Map<String, Object>) StringUtil.objectToMap(cu);
	   redisService.addHashMap(RedisPre.DB_USER+cu.getUserCode(), userMap);
	   return true;
   }
   
   /**
    * 获取用户信息
    * @param user
    * @return
    */
   public ChartUser getUserMap(String userCode){
	   try {
		   Map<?,?> queryMap=redisService.getHashMapKeys(RedisPre.DB_USER+userCode);
		   if(null==queryMap || StringUtil.isNUll((String)queryMap.get("userCode"))) {
			   return null;
		   }
		   return (ChartUser) StringUtil.mapToObject((Map<String, Object>) queryMap, ChartUser.class);
	} catch (Exception e) {
		logger.error("获取用户信息："+userCode, e);
	}
	   return null;
   }
   
   /**
    * 从数据库获取用户信息
    * @param userCode
    * @return
    */
   public ChartUser getUserByDB(String userCode) {
	   ChartUser cu=new ChartUser();
	   cu.setUserCode(userCode);
	   return this.userDao.getUser(cu);
   }
   
   /**
        * 获取所有在线用户
    * @return
    */
   public Set<ChartUser> getAllUpUser(){
	   List<String> userList=this.redisService.getAllUpUser();
	   Set<ChartUser> cuSet=new HashSet<ChartUser>();
	   for(String str:userList) {
		   try {
			   ObjectMapper om = new ObjectMapper();
			   cuSet.add((ChartUser)om.readValue(str, ChartUser.class));
		} catch (Exception e) {
			logger.error("获取在线用户出错!", e);
		}
	   }
	   return cuSet;
   }
   
    /**
	  * 添加用户
	 * @param user
	 */
	public Map<String,Object> addUser(ChartUser user) {
		ChartUser cu=new ChartUser();
		cu.setUserCode(user.getUserCode());
		cu=this.getUser(cu);
		if(null!=cu) {
			return StringUtil.returnMap("F", "用户编码已存在!");
		}
		
		user.setUserStatus("0");
	    user.setUserPassword(StringUtil.toMD5(user.getUserPassword()+user.getUserCode()));
		userDao.addUser(user);
		return StringUtil.returnSucess();
	}
	
	
	/**
	  * 修改用户
	 * @param user
	 */
	public void updateUser(ChartUser user) {
		userDao.updateUser(user);
	}
	
  
	
	
	/**
	  *    获取用户
	 * @param user
	 * @return
	 */
	public ChartUser getUser(ChartUser user) {

		if(!StringUtil.isNUll(user.getUserPassword())){
			user.setUserPassword(StringUtil.toMD5(user.getUserPassword()+user.getUserCode()));
		}
		
        ChartUser cu=getUserMap(user.getUserCode());
		if(null==cu || StringUtil.isNUll(cu.getUserCode())) {
			//获取数据库内容,添加缓存数据
			cu=userDao.getRedisUser(user);
			
			if(null==cu) {
				return null;
			}
			
			addUserMap(cu);
			cu.setUserPassword("");
			return cu;
		}else {
			if(!StringUtil.isNUll(user.getUserPassword())){
				if(cu.getUserPassword().equals(user.getUserPassword())){
					return cu;
				}else {
					return null;
				}
			}else {
				return cu;
			}
		}
	}
	
	/**
	 * 当用户再客户端登录的时候后绑定服务端进行校验
	 * @param user
	 * @param token
	 * @return
	 */
	public boolean addUserLoginToken(ChartUser user,String token) {
		if(user==null || StringUtil.isNUll(user.getUserCode())) {
			return false;
		}
		this.redisService.set(RedisPre.DB_USER_LOGIN_TOKEN+user.getUserCode(),token);
		this.redisService.expireKey(RedisPre.DB_USER_LOGIN_TOKEN+user.getUserCode(), 60);
		return true;
	}
	/**
	 * 从redis获取用户的数量
	 * @return
	 */
	public int getAllRedisUser() {
		return redisService.getCountPrex(RedisPre.DB_USER+"*");
	}
	
	/**
	 * 获取登录用户总数
	 * @return
	 */
	public int getAllLoginUserCount() {
		return redisService.getSetCount(RedisPre.NETTY_USER_SET).intValue();
	}
	
	/**
	  *   获取用户总数
	 * @param queryMap
	 * @return
	 */
	public int getAllUserCount(Map<String,String> queryMap) {
		return userDao.getAllUserCount(queryMap);
	}
	
	/**
	   * 获取所有用户数据
	 * @param searchMap
	 * @return
	 */
	public Set<ChartUser> getAllUser(Map<String,String> searchMap){
		return userDao.getAllUser(searchMap);
	}
	
	/**
	   * 获取带密码的数据
	 * @param searchMap
	 * @return
	 */
	public Set<ChartUser>getRedisAllUser(Map<String,String>searchMap){
		return userDao.getRedisAllUser(searchMap);
	}
	
	/**
	  * 获取最近聊天得用户
	 * @param cu
	 * @return
	 */
	public Set<ChartUser> getUserOldChat(ChartUser cu){
		return userDao.getUserOldChat(cu);
	}
	
	
	//-------------非DAO数据，逻辑处理 开始--------------------------------------------
	
	/**
	   *   数据状状态同步
	 * @param userCode
	 * @param userStatus
	 */
	public void dbDownUser(String userCode,String userStatus){
		if(StringUtil.isNUll(userCode)){
			return;
		}
		
		Set<String> userCodes=new HashSet<String>();
		userCodes.add(userCode);
		dbDownUser(userCodes, userStatus);
	}
	
	/**
	   *   这里没用in操作，后续自行修改
	 * @param userCode
	 * @param userStatus
	 */
	public void dbDownUser(Set<String> userCode,String userStatus){
          if(null!=userCode && userCode.size()>0) {
        	  for(String str:userCode) {
        		  //从redis获取数据
        		  ChartUser currentCu=new ChartUser();
        		  currentCu.setUserCode(str);
        		  ChartUser cu=(ChartUser) this.getUser(currentCu);
        		  
        		  //注销、或其他原因，获取不到数据
        		  if(null==cu) {
        			  continue;
        		  }
        		  
        		  cu.setUserStatus(userStatus);
                  //数据库更新
        		  userDao.updateUser(cu);
        		  
        		  //1.删除绑定信息
        		  //redisService.delGroupUser(RedisPre.NETTY_USER_SET, "userCode", cu.getUserCode());
        		  redisService.removeSet(RedisPre.NETTY_USER_SET, cu);
        		  if("-1".equals(userStatus)) {
        			//删除用户信息
        			redisService.delete(RedisPre.DB_USER+cu.getUserCode());
					
        			//删除群组信息
        			Set<String> groupSet = redisService.getSetPrex(RedisPre.DB_GROUP_SET + "*");
					if (null != groupSet && !groupSet.isEmpty()) {
						for (String groupCode : groupSet) {
							//redisService.delGroupUser(groupCode, "userCode", cu.getUserCode());
							redisService.removeSet(groupCode, cu);
						}
					}
        		  }else {
        			//更新用户信息
        			redisService.addHashMap(RedisPre.DB_USER+cu.getUserCode(), "userStatus", userStatus);
        			cu.setUserStatus(userStatus);
        			//重新绑定 0禁言 1在线
          		    redisService.addSet(RedisPre.NETTY_USER_SET,cu);
        		  }
                  cu=null;
        	  }
          } 		
	}
	//-------------非DAO数据，逻辑处理 结束---------------------------------------------
	
	/**
	   * 获取用户注册数据
	 * @param day
	 * @return
	 */
	public List<Map<String,String>> getUserRegsitCount(int day){
		return userDao.getUserRegsitCount(day);
	}
	
	/**
	  * 获取IP统计数据
	 * @return
	 */
	public List<Map<String,Object>> getIPCount(){
		return userDao.getIPCount();
	}

	public ChartUser getChartUser(String userCode) {
		if(!StringUtil.isNUll(userCode)) {
			 ChartUser cu=new ChartUser();
			 cu.setUserCode(userCode);
			 return getUser(cu);
		}else {
		     return null;
		}
	}

	public ChartUser getChartOnUser(String userCode) {
		if(!StringUtil.isNUll(userCode)) {
			 return getUserMap(userCode);
		}else {
		     return null;
		}
	}

	public void sendAlertMsgByCode(String userCode, String msg) {
		logger.info("广播用户:" + userCode);
		if(StringUtil.isNUll(userCode) || null==getChartUser(userCode)) {
			return;
		}
		
		Message message=new Message();
		message.setMsg(msg);
		ChartUser admin=new ChartUser();
		admin.setUserCode("admin");
		admin.setUserName("管理员");
		message.setFrom(admin);
		message.setCmd("3");
		
		ChartUser cu=new ChartUser();
		cu.setUserCode(userCode);
		message.setAccept(getUser(cu));
		
		message.setCreateDate(StringUtil.format(new Date()));
		
		redisService.SendMsg(message);
		
	}

	public void removeChannelByCode(String userCode) {
		logger.info("移除用户:" + userCode);
		if(StringUtil.isNUll(userCode) || null==getChartUser(userCode)) {
			return;
		}
		ChartUser cu=getChartUser(userCode);
		//移除群组
		removeGroup(userCode);
		//删除服务端绑定信息
		redisService.removeSet(RedisPre.NETTY_USER_SET, cu);
	    //redisService.delGroupUser(RedisPre.NETTY_USER_SET, "userCode", cu.getUserCode());
		//删除绑定数据
	    redisService.delete(RedisPre.DB_USER+cu.getUserCode());
		//userService.dbDownUser(userCode, "0");
		
	}

	@Override
	public void removeGroup(String userCode) {
		if(StringUtil.isNUll(userCode)) {
			return;
		}
		
		Set<String> groupSet=redisService.getSetPrex(RedisPre.DB_GROUP_SET+"*");
		if(null==groupSet || groupSet.isEmpty()) {
			return;
		}
		
		//ChartUser cu=getChartUser(userCode);
		for(String str:groupSet) {
			//删除群组里面的信息
		   //redisService.delGroupUser(str, "userCode", userCode);
			redisService.removeSet(str, getChartUser(userCode));
		}
	}
}
