package com.persagy.functions.weather.thread;

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

import org.apache.log4j.Logger;

import com.persagy.ems.pojo.wz.HourRecordData;
import com.persagy.framework.util.BeanUtils;
import com.persagy.framework.util.ConfigUtil;
import com.persagy.framework.util.DateUtils;
import com.persagy.framework.util.WServiceUtil;
import com.persagy.functions.weather.constant.Const;
import com.persagy.functions.weather.dto.NowAirDTO;
import com.persagy.functions.weather.dto.NowWeatherDTO;
import com.persagy.functions.weather.service.HourRecordService;

/**
 * 小时天气数据记录
 */
public class HourDataRecordThread implements Runnable {
	private static final Logger log = Logger.getLogger(HourDataRecordThread.class);
	
	private static boolean firstRun = true;

	private static Set<String> updateCitySet = new HashSet<>();
	
	private HourRecordService service;
	
	private static final String tname = "hourRecord";
	
	public HourDataRecordThread(HourRecordService service) {
		this.service = service;
	}
	
	@Override
	public void run() {

		log.info(tname + " 线程启动...");
		while(true) {
			updateMap();
			
			if(!updateCitySet.isEmpty()) {
				
				Long sleepMinlliseconds = Const.AboutTime.minMinlliseconds;
				
				Date dateNow = new Date();
				int minIndex = DateUtils.getMinute(dateNow);
				Date dateHour = null;
				try {
					dateHour = DateUtils.getShortDate(dateNow, 2);
				} catch (Exception e1) {
					e1.printStackTrace();
				}
				Date dateHourHalf = DateUtils.getMinuteOff(dateHour, 30);
				
				if(minIndex < 30) {
					sleepMinlliseconds = dateHour.getTime() + Const.AboutTime.min30Minlliseconds - dateNow.getTime();
				}else {
					String executeResult = hourRecordHandle(dateHour);
					
					if(firstRun) {
						firstRun = false;
					}
					
					sleepMinlliseconds = dateHourHalf.getTime() + Const.AboutTime.hourMilliseconds - new Date().getTime();
					
					log.info(tname + " executed:"+executeResult + ". sleep "+(sleepMinlliseconds / (1000.0 * 60))+" min");
				}
				
				try {
					Thread.sleep(sleepMinlliseconds);
				}catch (Exception e) {
					e.printStackTrace();
				}
			}else {
				log.info(tname + " executed:no city need to record hour data, sleep 1 min");
				try {
					Thread.sleep(Const.AboutTime.minMinlliseconds);
				}catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	private String hourRecordHandle(Date dateHour) {
		int saveTotal = updateCitySet.size();
		int saveFailedNum = 0;
		Set<String> saveFailedSet = new HashSet<>();
		int saveSuccessNum = 0;
		int undoNum = 0;
		Set<String> undoSet = new HashSet<>();
		
		long startTime = System.currentTimeMillis();
		for(String cityId : updateCitySet) {
			try {
				boolean requestService = true;
				
				if(firstRun) {
					List<HourRecordData> hrdList = this.service.queryForRightHour(cityId, dateHour);
					if ((hrdList != null) && (!hrdList.isEmpty())) {
						requestService = false;
					}
				}
				
				if(requestService) {
					NowWeatherDTO nowWeather = WServiceUtil.getNowWeatherObj(cityId);
					NowAirDTO nowAir = WServiceUtil.getNowAirObj(cityId);
					
					HourRecordData hrd = combineData(nowWeather, nowAir);
					if(hrd.flag) {
						hrd.setCityId(cityId);
						hrd.setHourTime(dateHour);
						service.save(hrd);
						saveSuccessNum ++;
					}
				}else {
					undoNum ++;
					undoSet.add(cityId);
				}
			} catch (Exception e) {
				saveFailedNum ++;
				saveFailedSet.add(cityId);
				e.printStackTrace();
			}
		}
		
		String resultMsg = "total-success-failed-undo=" + saveTotal + "-" + saveSuccessNum + "-" + saveFailedNum + "-" + undoNum;
		if(saveFailedNum != undoNum) {
			resultMsg += ", saveFailed=" + saveFailedSet+", undo=" + undoSet;
		}
		long endTime = System.currentTimeMillis();
		return resultMsg + ", timeCost=" + (endTime - startTime) / 1000L + "s";
	}
	
	private HourRecordData combineData(NowWeatherDTO nowWeather, NowAirDTO nowAir) {
		HourRecordData hrd = new HourRecordData();
		
		if(null == nowWeather && null == nowAir) {
			return hrd;
		}
		
		
		String last_update = null;
		
		if(null != nowWeather) {
			last_update = nowWeather.getLast_update();
			nowWeather.setLast_update(null);
			
			try {
				BeanUtils.copyBean(nowWeather, hrd);
				hrd.setLastUpdateNow(DateUtils.t8DateStr2Date(last_update));
				hrd.flag = true;
			}catch (Exception e) {
			}
			
		}
		
		if(null != nowAir) {
			last_update = nowAir.getLast_update();
			nowAir.setLast_update(null);
			
			try {
				BeanUtils.copyBean(nowAir, hrd);
				if(last_update != null) {
					hrd.setLastUpdateAir(DateUtils.t8DateStr2Date(last_update));
				}
				hrd.flag = true;
			}catch (Exception e) {
			}
		}
		
		return hrd;
	}

	private void updateMap() {
		Set<String> hourCitySet = new HashSet<>(ConfigUtil.getHourCitySet());
		
		if(!hourCitySet.isEmpty()) {
			int addNum = 0;
			for(String cityId : hourCitySet) {
				if(!updateCitySet.contains(cityId)) {
					addNum ++;
				}
				updateCitySet.add(cityId);
			}
			if(addNum > 0) {
				log.info("hour cirty add " + addNum);
			}
		}
	}
}
