package com.persagy.functions.weather.thread;

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

import org.apache.log4j.Logger;

import com.persagy.core.enumeration.SpecialOperator;
import com.persagy.core.mvc.service.CoreService;
import com.persagy.ems.pojo.wz.ApiRequester;
import com.persagy.ems.pojo.wz.BusinessApiStatic;
import com.persagy.framework.util.DateUtils;

public class RequestIpStatisticThread implements Runnable {
	public static boolean initState = false; 
	private static final Logger log = Logger.getLogger(RequestIpStatisticThread.class);
	private static final String logPrefix = "RequestIpStatistic";
	private static final String sptStr = "@";
	private CoreService coreService;
	/** {ip@api名称:数据更新到的截止时间} */
	private static Map<String, Date> ipApi_endDate = new HashMap<>();
	/** {ip@api名称:请求次数} */
	private static Map<String, Integer> ipApi_number = new HashMap<>();
	private static Set<String> newIp_api = new HashSet<>();
	
	public static void addIp(String ip, String api) {
		synchronized (newIp_api) {
			newIp_api.add(ip+sptStr+api);
			ipApi_number.put(ip+sptStr+api, 0);
		}
	}
	
	public static Set<String> flushIp() {
		synchronized (newIp_api) {
			Set<String> result = new HashSet<>(newIp_api);
			newIp_api.clear();
			return result;
		}
	}
	
	/**
	 * 增加缓存数据 {ip@api名称:数据更新到的截止时间}
	 * @param ip
	 * @param api
	 */
	public static void addupdateIpApiEndDateMap(String ip, String api) {
		if(!ipApi_endDate.containsKey(ip+sptStr+api)) {
			Date todayStart = new Date();
			try {
				todayStart = DateUtils.getShortDate(new Date(), 3);
			} catch (Exception e) {
				e.printStackTrace();
			}

			ipApi_endDate.put(ip+sptStr+api, todayStart);
			addIp(ip, api);
			
			log.info(logPrefix+"-> add ipRecord to ip+api2date map");
		}
	}
	
	public RequestIpStatisticThread(CoreService coreService) {
		this.coreService = coreService;
	}
	
	@Override
	public void run() {
		log.info(logPrefix+"-> 线程启动");
		
		while(true) {
			long sleepTime = 1000 * 60 * 60 + 3000;
			
			Date todayStart = new Date();
			try {
				todayStart = DateUtils.getShortDate(new Date(), 3);
			} catch (Exception e) {
				e.printStackTrace();
			}
			
			String[] ipApiArray = null;
			Set<String> newIpSet = flushIp();
			if(!newIpSet.isEmpty()) {
				List<ApiRequester> saveList = new ArrayList<>();
				for(String ipApi : newIpSet) {
					ipApiArray = ipApi.split(sptStr);
					ApiRequester saveObj = new ApiRequester();
					saveObj.setIp(ipApiArray[0]);
					saveObj.setApiName(ipApiArray[1]);
					saveObj.setDataEndTime(todayStart);
					saveObj.setInsertTime(todayStart);
					saveObj.setUpdateTime(todayStart);
					saveObj.setApiNum(0);
					saveList.add(saveObj);
				}
				try {
					coreService.save(saveList);
					log.info(logPrefix+"-> insert new ipRecord, number=" + saveList.size());
				}catch (Exception e) {
					log.error(logPrefix+"-> insert new ipRecord error");
					e.printStackTrace();
				}
			}
			
			// {ip@api名称:数据更新到的截止时间}
			Map<String, Date> baseMap = new HashMap<>(ipApi_endDate);
			
			if(!baseMap.isEmpty()) {
				BusinessApiStatic queryBas = new BusinessApiStatic();
				List<BusinessApiStatic> basList = null;
				
				Date dataEndDate = null;
				
				int updateNum = 0;
				
				for(String ipApi : baseMap.keySet()) {
					dataEndDate = baseMap.get(ipApi);
					
					if(dataEndDate.before(todayStart)) {
						basList = null;
						
						ipApiArray = ipApi.split(sptStr);
						queryBas.setIp(ipApiArray[0]);
						queryBas.setApi(ipApiArray[1]);
						queryBas.setSpecialOperation("hourTime", SpecialOperator.$gte, dataEndDate);
						queryBas.setSpecialOperation("hourTime", SpecialOperator.$lt, todayStart);
						
						try {
							basList = coreService.query(queryBas);
						} catch (Exception e) {
							e.printStackTrace();
						}
						
						if(null != basList) {
							int addNum = 0;
							for(BusinessApiStatic obj : basList) {
								if(obj.getNum() != null) {
									addNum += obj.getNum();
								}
							}
							
							if(addNum > 0) {
								try {
									ApiRequester arQuery = new ApiRequester();
									arQuery.setIp(ipApiArray[0]);
									arQuery.setApiName(ipApiArray[1]);
									List<ApiRequester> oldList = coreService.query(arQuery);
									
									ApiRequester saveObj = null;
									if(null == oldList || oldList.isEmpty()) {
										arQuery.setApiNum(addNum);
										arQuery.setDataEndTime(todayStart);
										arQuery.setInsertTime(new Date());
										arQuery.setUpdateTime(new Date());
										saveObj = arQuery;
									}else {
										saveObj = oldList.get(0);
										if(saveObj.getApiNum() != null) {
											saveObj.setApiNum(addNum + saveObj.getApiNum());
										}else {
											saveObj.setApiNum(addNum);
										}
										saveObj.setDataEndTime(todayStart);
										saveObj.setUpdateTime(new Date());
										coreService.remove(arQuery);
									}
									
									coreService.save(saveObj);
									ipApi_endDate.put(ipApi, todayStart);
									updateNum ++;
								}catch (Exception e) {
									e.printStackTrace();
								}
							}
						}
					}
				}
				
				log.info(logPrefix+"-> update ipRecord, size=" + updateNum);
			}
			
			try {
				Thread.sleep(sleepTime);
			}catch (Exception e) {
			}
		}
	}
	
	/**
	 * 初始化缓存数据 {ip@api名称:数据更新到的截止时间}
	 */
	public void init() {
		if(initState) {
			return;
		}
		
		Map<String, Date> result = new HashMap<>();
		
		ApiRequester queryObj = new ApiRequester();
		int count = 0;
		try {
			count = coreService.count(queryObj);
		}catch (Exception e) {
		}
		
		
		if(count > 0) {
			final long pageCount = 1000;
			
			List<ApiRequester> list = null;
			if(count > pageCount) {
				long skip = 0;
				do {
					queryObj.setSkip(skip);
					queryObj.setLimit(pageCount);
					list = null;
					try {
						list = coreService.query(queryObj);
					} catch (Exception e) {
					}
					
					if(list != null) {
						if(list.isEmpty()) {
							break;
						}else {
							for(ApiRequester obj : list) {
								result.put(obj.getIp()+sptStr+obj.getApiName(), obj.getDataEndTime());
								ipApi_number.put(obj.getIp()+sptStr+obj.getApiName(), obj.getApiNum());
							}
						}
					}
					
					skip += pageCount;
				}while(skip < count);
			}else {
				try {
					list = coreService.query(queryObj);
				} catch (Exception e) {
				}
				
				if(null != list) {
					for(ApiRequester obj : list) {
						result.put(obj.getIp()+sptStr+obj.getApiName(), obj.getDataEndTime());
						ipApi_number.put(obj.getIp()+sptStr+obj.getApiName(), obj.getApiNum());
					}
				}
			}
		}
		
		log.info(logPrefix+"-> init ip+api2date map, size=" + result.size());
		ipApi_endDate.putAll(result);
		
		initState = true;
	}
}
