package com.persagy.functions.weather.service.impl;

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

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.persagy.ems.pojo.wz.DayStaticRecord;
import com.persagy.framework.util.DateUtils;
import com.persagy.functions.weather.dto.TempStatisticsDTO;
import com.persagy.functions.weather.service.DayStaticService;
import com.persagy.functions.weather.service.WeatherStatisticsService;

@Service
public class WeatherStatisticsServiceImpl implements WeatherStatisticsService {

	@Resource(name = "dayStaticService")
	private DayStaticService dayStaticService;

	@Override
	public TempStatisticsDTO getTempMonthStatisticsDTO(String cityCode, Date startDate, Date endDate) throws Exception {
		List<DayStaticRecord> staticRecords = dayStaticService.query(cityCode, startDate, endDate);
		if (null == staticRecords || staticRecords.isEmpty()) {
			return null;
		}

		TempStatisticsDTO statisticsDTO = initTempStatisticsDTO(staticRecords);
		statisticsDTO.setMonthTempMap(getMonthTempMap(staticRecords));
		return statisticsDTO;
	}

	private Map<Date, Double> getMonthTempMap(List<DayStaticRecord> staticRecords) {
		Map<Date, List<Double>> monthTempMap = new HashMap<>();
		Date dayDate = null;
		for (DayStaticRecord dayWeather : staticRecords) {
			dayDate = dayWeather.getDayTime();
			Double maxTemp = dayWeather.getMaxTemp();
			Double minTemp = dayWeather.getMinTemp();
			Date month = DateUtils.getFirstDayOfMonth(dayDate);
			if (monthTempMap.containsKey(month)) {
				monthTempMap.get(month).add((maxTemp.doubleValue() + minTemp.doubleValue()) / 2.0);
			} else {
				List<Double> dataList = new ArrayList<>();
				dataList.add((maxTemp.doubleValue() + minTemp.doubleValue()) / 2.0);
				monthTempMap.put(month, dataList);
			}
		}
		Map<Date, Double> resultMap = new HashMap<>();
		for (Date month : monthTempMap.keySet()) {
			List<Double> tempList = monthTempMap.get(month);
			Double avgMonth = getDoubleSum(tempList);
			if (null != avgMonth) {
				avgMonth = avgMonth / tempList.size();
			}
			resultMap.put(month, avgMonth);
		}
		return resultMap;
	}

	private TempStatisticsDTO initTempStatisticsDTO(List<DayStaticRecord> staticRecords) {
		Double maxTemp = null;
		Double minTemp = null;
		List<Double> avgTempList = new ArrayList<>();

		for (DayStaticRecord weather : staticRecords) {
			Double dayMaxTemp = weather.getMaxTemp();
			Double dayMinTemp = weather.getMinTemp();
			Double dayAvgTemp = null;
			
			if(null != dayMaxTemp && null != dayMinTemp) {
				dayAvgTemp = (dayMaxTemp + dayMinTemp) / 2.0;
			}
			
			if(null != dayMaxTemp) {
				maxTemp = maxTemp == null ? dayMaxTemp : dayMaxTemp > maxTemp ? dayMaxTemp : maxTemp;
			}
			
			if(null != dayMinTemp) {
				minTemp = minTemp == null ? dayMinTemp : dayMinTemp < minTemp ? dayMinTemp : minTemp;
			}
			avgTempList.add(dayAvgTemp);
		}

		Double avgTemp = getDoubleSum(avgTempList);
		if (null != avgTemp) {
			avgTemp = avgTemp / avgTempList.size();
		}

		TempStatisticsDTO statisticsDTO = new TempStatisticsDTO();
		statisticsDTO.setMaxTemp(maxTemp);
		statisticsDTO.setMinTemp(minTemp);
		statisticsDTO.setAvgTemp(avgTemp);

		return statisticsDTO;
	}

	private Double getDoubleSum(List<Double> dataList) {
		if (dataList == null || dataList.isEmpty()) {
			return null;
		}
		Double sum = null;
		for (Double data : dataList) {
			if (data != null) {
				sum = sum == null ? data : sum + data;
			}
		}
		return sum;
	}

	@Override
	public TempStatisticsDTO getTempBuildingStatisticsDTO(List<String> cityCodeList, Date startDate, Date endDate)
			throws Exception {

		List<DayStaticRecord> staticRecords = new ArrayList<>();
		for (String cityCode : cityCodeList) {
			List<DayStaticRecord> staticRecordTemp = dayStaticService.query(cityCode, startDate, endDate);
			if (null != staticRecordTemp) {
				staticRecords.addAll(staticRecordTemp);
			}
		}

		if (staticRecords.isEmpty()) {
			return null;
		}

		TempStatisticsDTO statisticsDTO = initTempStatisticsDTO(staticRecords);
		statisticsDTO.setBuildingTempMap(getBuildingTempMap(staticRecords));
		return statisticsDTO;
	}

	private Map<String, Double> getBuildingTempMap(List<DayStaticRecord> staticRecords) {
		Map<String, List<Double>> buildingTempListMap = new HashMap<>();
		for (DayStaticRecord weatherDay : staticRecords) {
			String cityCode = weatherDay.getCityId();
			Double maxTemp = weatherDay.getMaxTemp();
			Double minTemp = weatherDay.getMinTemp();
			if (buildingTempListMap.containsKey(cityCode)) {
				buildingTempListMap.get(cityCode).add((maxTemp + minTemp) / 2.0);
			} else {
				List<Double> tempList = new ArrayList<>();
				tempList.add((maxTemp + minTemp) / 2.0);
				buildingTempListMap.put(cityCode, tempList);
			}
		}
		Map<String, Double> buildingTempMap = new HashMap<>();
		for (String cityCode : buildingTempListMap.keySet()) {
			List<Double> tempList = buildingTempListMap.get(cityCode);
			Double avgTemp = getDoubleSum(tempList).doubleValue();
			if (null != avgTemp) {
				avgTemp = avgTemp / tempList.size();
			}
			buildingTempMap.put(cityCode, avgTemp);
		}
		return buildingTempMap;
	}
}