package com.platform.modules.live.service.impl;

import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.platform.common.utils.ConfigConstant;
import com.platform.common.utils.DateUtils;
import com.platform.common.utils.RedisContants;
import com.platform.common.utils.RedisUtils;
import com.platform.modules.live.dao.LiveSceneCountDao;
import com.platform.modules.live.entity.LiveSceneCountEntity;
import com.platform.modules.live.service.LiveSceneCountService;
import com.platform.modules.live.utils.CalculateSceneCountUtils;
import com.platform.modules.live.vo.SceneCountVo;
import com.platform.modules.sys.entity.SysConfigEntity;
import com.platform.modules.sys.service.SysConfigService;
import org.springframework.transaction.annotation.Transactional;

@Service("liveSceneCountService")
@Transactional
public class LiveSceneCountServiceImpl extends ServiceImpl<LiveSceneCountDao, LiveSceneCountEntity> implements LiveSceneCountService {
	
	@Autowired
    private SysConfigService sysConfigService;
	@Autowired
	private RedisUtils redisUtils;

	@Override
	public void save(LiveSceneCountEntity liveSceneCount){
		this.baseMapper.insert(liveSceneCount);
	}
	
	@Override
	public void update(LiveSceneCountEntity liveSceneCount){
		this.baseMapper.update(liveSceneCount, null);
	}
	
	@Override
	public void delete(Integer sceneId){
		this.baseMapper.deleteById(sceneId);
	}
	
	@Override
	public void deleteBatch(Integer[] sceneIds){
		this.baseMapper.deleteBatchIds(Arrays.asList(sceneIds));
	}
	
	@Override
	@Transactional(readOnly = true)
	public SceneCountVo info(Integer id){
		return this.baseMapper.info(id);
	}
	
	@Override
	@Transactional(readOnly = true)
	public SceneCountVo findRedisById(Integer sceneId){
		
		String key = RedisContants.SCENE_COUNT;
		String fieid = RedisContants.SCENE_COUNT + sceneId;
		//总浏览量
		SceneCountVo sceneCountVo = redisUtils.hget(key, fieid, SceneCountVo.class);
		if(sceneCountVo == null) {
			sceneCountVo = this.baseMapper.info(sceneId);
			if(sceneCountVo == null) {
				sceneCountVo = new SceneCountVo();
				sceneCountVo.setViews(0);
				sceneCountVo.setViewsShow(0);
				sceneCountVo.setComments(0);
				sceneCountVo.setCommentsShow(0);
			} else {
				sceneCountVo.setViews(sceneCountVo.getViews() == null ? 0 : sceneCountVo.getViews());
				sceneCountVo.setViewsShow(sceneCountVo.getViewsShow() == null ? 0 : sceneCountVo.getViewsShow());
				sceneCountVo.setComments(sceneCountVo.getComments() == null ? 0 : sceneCountVo.getComments());
				sceneCountVo.setCommentsShow(sceneCountVo.getCommentsShow() == null ? 0 : sceneCountVo.getCommentsShow());
			}
			redisUtils.hset(key, fieid, sceneCountVo);
		}
		return sceneCountVo;
	}
	
	@Override
	public void cleanRedisSceneCountJob(){
		String key = RedisContants.SCENE_COUNT;
		redisUtils.delete(key);
	}
	
	@Override
	public void freshRedisSceneCountToDB(){
		
		String key = RedisContants.SCENE_COUNT_VIEWS_ADD;
		Set<String> fieids = redisUtils.hkeys(key);
		
		Map<String, Object> sceneViews = new HashMap<String, Object>();
		if(fieids!=null && fieids.size()>0){
			for(String fieid : fieids){
				if(fieid==null || fieid.equals("")){
					continue;
				}
				String sceneIdStr = fieid.substring(fieid.lastIndexOf("_") + 1);
				Integer sceneId = StringUtils.isBlank(sceneIdStr) ? null : Integer.valueOf(sceneIdStr);
				if(sceneId == null) {
					continue;
				}
				JSONObject viewsJson = redisUtils.hget(key, fieid)==null ? null : redisUtils.hget(key, fieid,JSONObject.class);
				if(viewsJson==null || viewsJson.length()==0 || (viewsJson.isNull("addviews") && viewsJson.isNull("addShowViews"))){
					continue;
				}
				sceneViews.put("id", sceneId);
				try {
					sceneViews.put("views", viewsJson.get("addviews")==null ? 0 : viewsJson.getInt("addviews"));
					sceneViews.put("showViews", viewsJson.get("addShowViews")==null ? 0 : viewsJson.getInt("addShowViews"));
				} catch (JSONException e) {
					e.printStackTrace();
				}
				sceneViews.put("nowTime", new Date());
				this.baseMapper.freshRedisToDB(sceneViews);
			}
			redisUtils.delete(key);
		}
		clearCount();
	}
	
	private void clearCount() {
		Calendar curr = Calendar.getInstance();
		Calendar last = Calendar.getInstance();
		String sceneCountClearTime = sysConfigService.getValue(ConfigConstant.SCENE_COUNT_CLEAR_TIME);
		if(StringUtils.isBlank(sceneCountClearTime)){
			SysConfigEntity config = new SysConfigEntity();
			config.setKey(ConfigConstant.SCENE_COUNT_CLEAR_TIME);
			config.setValue(DateUtils.format(new Date(), DateUtils.DATE_PATTERN));
			config.setRemark("现场计数器清除时间");
			sysConfigService.save(config);
			return;
		}
		last.setTime(DateUtils.stringToDate(sceneCountClearTime, DateUtils.DATE_PATTERN));
		int currDay = curr.get(Calendar.DAY_OF_YEAR);
		int lastDay = last.get(Calendar.DAY_OF_YEAR);
		if (currDay != lastDay) {
			curr.setFirstDayOfWeek(Calendar.MONDAY);
			last.setFirstDayOfWeek(Calendar.MONDAY);
			int currWeek = curr.get(Calendar.WEEK_OF_YEAR);
			int lastWeek = last.get(Calendar.WEEK_OF_YEAR);
			int currMonth = curr.get(Calendar.MONTH);
			int lastMonth = last.get(Calendar.MONTH);
			sysConfigService.updateValueByKey(ConfigConstant.SCENE_COUNT_CLEAR_TIME, DateUtils.format(new Date(curr.getTimeInMillis()), DateUtils.DATE_PATTERN));
			Map<String, Boolean> map = new HashMap<String, Boolean>();
			map.put("week", currWeek != lastWeek);
			map.put("month", currMonth != lastMonth);
			this.baseMapper.clearCount(map);
		}
	}
	
	@Override
	public Map<String, Object> getSceneCountByRedis(Integer sceneId){
		String key = RedisContants.SCENE_COUNT;
		String fieid = RedisContants.SCENE_COUNT + sceneId;
		//总浏览量
		SceneCountVo sceneCountVo = findRedisById(sceneId);
		sceneCountVo.setViews(sceneCountVo.getViews() + 1);
		int addShowViews = CalculateSceneCountUtils.CalculateSceneViewsUtils(1, sceneCountVo.getLiveStart());
		sceneCountVo.setViewsShow(sceneCountVo.getViewsShow() + addShowViews);
		sceneCountVo.setSceneId(sceneId);
		redisUtils.hset(key, fieid, sceneCountVo);
		
		// 更新浏览量
		String addKey = RedisContants.SCENE_COUNT_VIEWS_ADD;
		String addfieid = RedisContants.SCENE_COUNT_VIEWS_ADD + sceneId;
		
		JSONObject json = redisUtils.hget(addKey, addfieid)==null ? null : redisUtils.hget(addKey, addfieid,JSONObject.class);
		try {
			if(json==null){
				json = new JSONObject();
				json.put("addviews", 1);
				json.put("addShowViews", addShowViews);
			}else{
				if(json.isNull("addviews")){
					json.put("addviews", 1);
				}else{
					json.put("addviews", json.getInt("addviews")+1);
				}
				if(json.isNull("addShowViews")){
					json.put("addShowViews", addShowViews);
				}else{
					json.put("addShowViews", json.getInt("addShowViews")+addShowViews);
				}
			}
			redisUtils.hset(addKey, addfieid, json);
		} catch (JSONException e) {
			e.printStackTrace();
		}
		
		Map<String, Object> resultDate = new HashMap<String, Object>();
		resultDate.put("sceneId", sceneId);
		resultDate.put("viewsShow", sceneCountVo.getViewsShow());
		resultDate.put("commentsShow", sceneCountVo.getCommentsShow());
		return resultDate;
	}
	
	@Override
	public SceneCountVo updateRedisById(Integer sceneId,Integer viewsShow){
		String key = RedisContants.SCENE_COUNT;
		String fieid = RedisContants.SCENE_COUNT + sceneId;
		SceneCountVo sceneCountVo = findRedisById(sceneId);
		sceneCountVo.setViewsShow(viewsShow);
		redisUtils.hset(key, fieid, sceneCountVo);
		// 更新浏览量
		String addKey = RedisContants.SCENE_COUNT_VIEWS_ADD;
		String addfieid = RedisContants.SCENE_COUNT_VIEWS_ADD + sceneId;
		JSONObject json = redisUtils.hget(addKey, addfieid)==null ? null : redisUtils.hget(addKey, addfieid,JSONObject.class);
		try {
			if(json==null){
				json = new JSONObject();
				json.put("addviews", 0);
			}
			json.put("addShowViews", 0);
			redisUtils.hset(addKey, addfieid, json);
		} catch (JSONException e) {
			e.printStackTrace();
		}
		
		return sceneCountVo;
	}
	
}
