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.ems.pojo.wz.DayHisRecord;
import com.persagy.ems.pojo.wz.HourRecordData;
import com.persagy.framework.util.ConfigUtil;
import com.persagy.framework.util.DateUtils;
import com.persagy.functions.weather.constant.ConstStatisticType;
import com.persagy.functions.weather.service.DayHisRecordService;
import com.persagy.functions.weather.service.DayStaticService;
import com.persagy.functions.weather.service.HourRecordService;

public class HourToDayDataComputeThread implements Runnable {
	private static final Logger LOGGER = Logger.getLogger(HourToDayDataComputeThread.class);
	private HourRecordService hourDataService;
	private DayHisRecordService dayHisRecordService;
	private DayStaticService dayStaticService;
	private String cityId;
	private Set<String> cityIds;
	private Date fromDay;
	private Date toDay;
	private ConstStatisticType stype;
	
	public HourToDayDataComputeThread(HourRecordService hourDataService, DayHisRecordService dayHisRecordService,
			DayStaticService dayStaticService, String cityId, Date fromDay, Date toDay) {
		super();
		this.hourDataService = hourDataService;
		this.dayHisRecordService = dayHisRecordService;
		this.dayStaticService = dayStaticService;
		this.cityId = cityId;
		this.fromDay = fromDay;
		this.toDay = toDay;
	}

	public HourToDayDataComputeThread(HourRecordService hourDataService, DayHisRecordService dayHisRecordService,
			DayStaticService dayStaticService, String cityId, Date fromDay, Date toDay, ConstStatisticType stype) {
		super();
		this.hourDataService = hourDataService;
		this.dayHisRecordService = dayHisRecordService;
		this.dayStaticService = dayStaticService;
		this.cityId = cityId;
		this.fromDay = fromDay;
		this.toDay = toDay;
		this.stype = stype;
	}
	
	public HourToDayDataComputeThread(HourRecordService hourDataService, DayHisRecordService dayHisRecordService,
			DayStaticService dayStaticService, Set<String> cityIds, Date fromDay, Date toDay, ConstStatisticType stype) {
		super();
		this.hourDataService = hourDataService;
		this.dayHisRecordService = dayHisRecordService;
		this.dayStaticService = dayStaticService;
		this.cityIds = cityIds;
		this.fromDay = fromDay;
		this.toDay = toDay;
		this.stype = stype;
	}

	@Override
	public void run() {
		Set<String> hourCites = new HashSet<>();
		
		if(null != cityId) {
			if("ALL".equals(cityId)) {
				hourCites = ConfigUtil.getHourCitySet();
			}else {
				hourCites.add(cityId);
			}
		}else if(null != cityIds && !cityIds.isEmpty()){
			hourCites.addAll(cityIds);
		}else {
			LOGGER.warn("no city to do");
			return;
		}
		
		boolean ifBreak = false;
		int cindex = 1;
		for(String cid : hourCites) {
			Date sdate = fromDay;
			while(sdate.before(toDay)) {
				Date tdate = DateUtils.getDayOff(sdate, 50);
				if(tdate.after(toDay)) {
					tdate = toDay;
				}
				
				String dateS = null, dateE = null;
				try {
					dateS = DateUtils.date2Str(sdate, "yyyyMMdd");
					dateE = DateUtils.date2Str(tdate, "yyyyMMdd");
				}catch (Exception e) {
				}
				
				List<HourRecordData> hourDataList = null;
				try {
					hourDataList = hourDataService.query(cid, sdate, tdate);
				} catch (Exception e) {
					e.printStackTrace();
				}
				if(null != hourDataList && !hourDataList.isEmpty()) {
					Date updateTime = new Date();
					
					Map<Date, List<HourRecordData>> dayDate_list = new HashMap<>();
					for(HourRecordData obj : hourDataList) {
						Date dayDate = null;
						try {
							dayDate = DateUtils.getShortDate(obj.getHourTime(), 3);
						} catch (Exception e) {
							e.printStackTrace();
						}
						if(dayDate_list.containsKey(dayDate)) {
							dayDate_list.get(dayDate).add(obj);
						}else {
							List<HourRecordData> list = new ArrayList<>();
							list.add(obj);
							dayDate_list.put(dayDate, list);
						}
					}
					
					List<DayHisRecord> dayHisSave = new ArrayList<>();
					
					try {
						for(Date dayDate : dayDate_list.keySet()) {
							if(ifBreak) {
								break;
							}
							
							List<HourRecordData> list = dayDate_list.get(dayDate);
							String textDay = null, codeDay = null, textNight = null, codeNight = null;
							Double high = null, low = null, humiMax = null, humiMin= null, 
									visiMax= null, visiMin= null, winsMax= null, winsMin= null,
									presMax= null, presMin = null;
							Double avgHumi = null, avgWins = null, avgWindd = null;
							Integer avgWindL = null;
							int avgHumiNum = 0, avgWinsNum = 0, avgWinddNum = 0, avgWindLNum = 0;
							for(HourRecordData obj : list) {
								if(ifBreak) {
									break;
								}
								
								Double tmp = null;
								try {
									tmp = Double.parseDouble(obj.getTemperature());
								}catch (Exception e) {
								}
								high = getComp(high, tmp, true);
								low = getComp(low, tmp, false);
								
								Double hum = null;
								try {
									hum = Double.parseDouble(obj.getHumidity());
								}catch (Exception e) {
								}
								if(avgHumi == null) {
									avgHumi = hum;
									avgHumiNum ++;
								}else if(hum != null){
									avgHumi += hum;
									avgHumiNum ++;
								}
								humiMax = getComp(humiMax, hum, true);
								humiMin = getComp(humiMin, hum, false);
								
								Double visi = null;
								try {
									visi = Double.parseDouble(obj.getVisibility());
								}catch (Exception e) {
								}
								visiMax = getComp(visiMax, visi, true);
								visiMin = getComp(visiMin, visi, false);
								
								Double wins = null;
								try {
									wins = Double.parseDouble(obj.getWind_speed());
								}catch (Exception e) {
								}
								if(avgWins == null) {
									avgWins = wins;
									avgWinsNum ++;
								}else if(null != wins){
									avgWins += wins;
									avgWinsNum ++;
								}
								winsMax = getComp(winsMax, wins, true);
								winsMin = getComp(winsMin, wins, false);
								
								Double windd = null;
								try {
									windd = Double.parseDouble(obj.getWind_direction_degree());
								}catch (Exception e) {
								}
								if(avgWindd == null) {
									avgWindd = windd;
									avgWinddNum ++;
								}else if(windd != null){
									avgWindd += windd;
									avgWinddNum ++;
								}
								
								Integer winds = null;
								try {
									winds = Integer.parseInt(obj.getWind_scale());
								} catch (Exception e) {
								}
								if(avgWindL == null) {
									avgWindL = winds;
									avgWindLNum++;
								}else if(null != winds){
									avgWindL += winds;
									avgWindLNum++;
								}
								
								Double pres = null;
								try {
									Double.parseDouble(obj.getPressure());
								}catch (Exception e) {
								}
								presMax = getComp(presMax, pres, true);
								presMin = getComp(presMin, pres, false);
								
								if(DateUtils.getHour(obj.getHourTime()) == 12) {
									textDay = obj.getText();
									codeDay = obj.getCode();
								}
								
								if(DateUtils.getHour(obj.getHourTime()) == 20) {
									textNight = obj.getText();
									codeNight = obj.getCode();
								}
							}
							
							DayHisRecord dayHis = new DayHisRecord();
							
							dayHis.setUpdateTime(updateTime);
							dayHis.setCityId(cid);
							dayHis.setDayTime(dayDate);
							dayHis.setText_day(textDay);
							dayHis.setCode_day(codeDay);
							dayHis.setText_night(textNight);
							dayHis.setCode_night(codeNight);
							dayHis.setHigh(high+"");
							dayHis.setLow(low+"");
							if(avgWindd != null) {
								dayHis.setWind_direction_degree((avgWindd.intValue()/avgWinddNum)+"");
							}
							if(avgWindL != null) {
								dayHis.setWind_scale("" + (avgWindL.intValue()/avgWindLNum));
							}
							if(avgWins != null) {
								dayHis.setWind_speed("" + (avgWins.intValue()/avgWinsNum));
							}
							if(avgHumi != null) {
								dayHis.setHumidity((avgHumi.intValue()/avgHumiNum)+"");
							}
							dayHisSave.add(dayHis);
						}
						dayHisRecordService.saveBatch(dayHisSave);
						if(null != stype) {
							dayStaticService.restaticHourToDay(cid, dayDate_list, stype);
						}
						LOGGER.info("hourDataToDayData, time:[" + dateS + "," + dateE + "), cityNow:" + cindex + "/" + hourCites.size() + ", saveNum:" + dayHisSave.size());
					} catch (Exception e) {
						LOGGER.info("ErrorCity=" + cid); 
						ifBreak = true;
						e.printStackTrace();
					}
				}
				
				sdate = tdate;
				
				if(ifBreak) {
					break;
				}
			}
			cindex ++;
			
			if(ifBreak) {
				break;
			}
		}
		LOGGER.info("over");
	}

	private Double getComp(Double now, Double comp, boolean bigger) {
		if(comp == null) {
			return now;
		}
		if(now == null) {
			now = comp;
		}else if(bigger) {
			now = now < comp ? comp : now;
		}else {
			now = now > comp ? comp : now;
		}
		return now;
	}
}
