package com.persagy.framework.util;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import com.persagy.core.constant.SystemConstant;
import com.persagy.functions.weather.constant.Const;
import com.persagy.functions.weather.dto.AlarmDTO;
import com.persagy.functions.weather.dto.DayPredictDTO;
import com.persagy.functions.weather.dto.Hour24PredictDTO;
import com.persagy.functions.weather.dto.NowAirDTO;
import com.persagy.functions.weather.dto.NowWeatherDTO;
import com.persagy.functions.weather.dto.WeatherResponseDTO;

@SuppressWarnings("unchecked")
public class WServiceUtil {
	private static final Logger log = Logger.getLogger(WServiceUtil.class);
	
	public static Map<String, Object> getLocation(String location) {
		Map<String, Object> nowObj = new HashMap<>();

		String url = Const.ServiceURL.nowWeather;
		url = url.replace("LOCATION", location);

		try {
			String result = HttpUtil.get(url);
			Const.requestAdd(Const.API.nowWeather);
			Map<String, Object> resultMap = (Map<String, Object>) SystemConstant.jsonMapper.readValue(result,
					Map.class);
			List<Map<String, Object>> resultArray = (List<Map<String, Object>>) resultMap.get("results");
			Map<String, Object> dataItem = (Map<String, Object>) resultArray.get(0);
			nowObj = (Map<String, Object>) dataItem.get("location");
		} catch (Exception e) {
			log.error("请求实时天气数据失败！location=" + location + e.getMessage());
		}
		return nowObj;
	}
	
	/**
	 * 查询天气实况
	 * @param location 城市标识
	 * @return
	 * 
	 * {
	 * 	"text": "晴",
	 * 	"code": "0",
	 * 	"temperature": "13",
	 * 	"feels_like": "15",
	 * 	"pressure": "1008",
	 * 	"humidity": "18",
	 * 	"visibility": "18.7",
	 * 	"wind_direction": "南",
	 * 	"wind_direction_degree": "189",
	 * 	"wind_speed": "5.76",
	 * 	"wind_scale": "2",
	 * 	"clouds": "0",
	 * 	"dew_point": ""
	 * }
	 * 
	 */
	public static Map<String, Object> getNowWeather(String location) {
		Map<String, Object> nowObj = new HashMap<String, Object>();
		
		String url = Const.ServiceURL.nowWeather;
		url = url.replace(Const.LOCATION, location);
		
		try {
			String result = HttpUtil.get(url);
			Const.requestAdd(Const.API.nowWeather);
			Map<String, Object> resultMap = SystemConstant.jsonMapper.readValue(result, Map.class);
			List<Map<String, Object>> resultArray = (List<Map<String, Object>>) resultMap.get("results");
			Map<String, Object> dataItem = resultArray.get(0);
			nowObj = (Map<String, Object>) dataItem.get("now");
			nowObj.put("last_update", dataItem.get("last_update"));
		}catch (Exception e) {
			log.error("请求实时天气数据失败！location="+location + e.getMessage());
		}
		
		return nowObj;
	}
	
	/**
	 * 查询天气实况
	 * @param location 城市标识
	 * @return null
	 */
	public static NowWeatherDTO getNowWeatherObj(String location) {
		Map<String, Object> nowObj = getNowWeather(location);
		if(!nowObj.isEmpty()) {
			try {
				return map2Obj(nowObj, NowWeatherDTO.class);
			} catch (Exception e) {
				log.error("map转对象失败！", e);
			}
		}
		return null;
	}
	
	/**
	 * 查询空气质量实况数据
	 * @param location 城市标识
	 * @return 
	 * 
	 * {
	 * 	"aqi": "68",
	 * 	"pm25": "24",
	 * 	"pm10": "86",
	 * 	"so2": "2",
	 * 	"no2": "8",
	 * 	"co": "0.242",
	 * 	"o3": "83",
	 * 	"primary_pollutant": "PM10",
	 * 	"last_update": "2021-02-06T14:00:00+08:00",
	 * 	"quality": "良"
	 * }
	 * 
	 */
	public static Map<String, Object> getNowAir(String location) {
		Map<String, Object> nowObj = new HashMap<String, Object>();
		
		String url = Const.ServiceURL.nowAir;
		url = url.replace(Const.LOCATION, location);
		
		try {
			String result = HttpUtil.get(url);
			Const.requestAdd(Const.API.nowAir);
			Map<String, Object> resultMap = SystemConstant.jsonMapper.readValue(result, Map.class);
			List<Map<String, Object>> resultArray = (List<Map<String, Object>>) resultMap.get("results");
			Map<String, Object> dataItem = resultArray.get(0);
			Map<String, Object> cityMap = (Map<String, Object>) dataItem.get("air");
			nowObj = (Map<String, Object>) cityMap.get("city");
		}catch (Exception e) {
			log.error("请求空气质量实况数据失败！location="+location, e);
		}
		
		return nowObj;
	}
	
	/**
	 * 查询空气质量实况数据
	 * @param location 城市标识
	 * @return null
	 */
	public static NowAirDTO getNowAirObj(String location) {
		Map<String, Object> nowObj = getNowAir(location);
		if(!nowObj.isEmpty()) {
			try {
				return map2Obj(nowObj, NowAirDTO.class);
			}catch (Exception e) {
				log.error("map转对象失败！", e);
			}
		}
		return null;
	}
	
	/**
	 * 查询逐日天气预报和昨日天气数据
	 * @param location 城市标识
	 * @param start >=-2, <15
	 * @param end >-2, <=15
	 * @return
	 * 
	 * [
	 * 	{
	 * 		"date": "2021-02-07",
	 * 		"text_day": "晴",
	 * 		"code_day": "0",
	 * 		"text_night": "晴",
	 * 		"code_night": "1",
	 * 		"high": "6",
	 * 		"low": "-5",
	 * 		"rainfall": "0.0",
	 * 		"precip": "",
	 * 		"wind_direction": "东北",
	 * 		"wind_direction_degree": "45",
	 * 		"wind_speed": "3.0",
	 * 		"wind_scale": "1",
	 * 		"humidity": "35"
	 * 	}
	 * ]
	 * 
	 */
	public static List<Map<String, Object>> getDayPredict(String location, int start, int end) {
		List<Map<String, Object>> dailyArray = new ArrayList<Map<String, Object>>();
		
		String url = Const.ServiceURL.dayPredict;
		url = url.replace(Const.LOCATION, location).replace(Const.DAYSTART, start+"").replace(Const.DAYEND, end+"");
		try {
			String result = HttpUtil.get(url);
			Const.requestAdd(Const.API.dayPredict);
			Map<String, Object> resultMap = SystemConstant.jsonMapper.readValue(result, Map.class);
			List<Map<String, Object>> resultArray = (List<Map<String, Object>>) resultMap.get("results");
			Map<String, Object> dataItem = resultArray.get(0);
			dailyArray = (List<Map<String, Object>>) dataItem.get("daily");
			String last_update = (String) dataItem.get("last_update");
			if (dailyArray != null) {
				for (Map<String, Object> item : dailyArray) {
					item.put("last_update", last_update);
				}
			}
		}catch (Exception e) {
			log.error("查询逐日天气预报和昨日天气数据失败！location="+location+",start="+start+",end"+end, e);
		}
		return dailyArray;
	}
	
	/**
	 * 查询逐日天气预报和昨日天气数据
	 * @param location 城市标识
	 * @param start >=-2, <15
	 * @param end >-2, <=15
	 * @return
	 */
	public static List<DayPredictDTO> getDayPredictObj(String location, int start, int end) {
		List<DayPredictDTO> dataList = new ArrayList<>();
		List<Map<String, Object>> dailyArray = getDayPredict(location, start, end);
		if(!dailyArray.isEmpty()) {
			try {
				for(Map<String, Object> map : dailyArray) {
					dataList.add(map2Obj(map, DayPredictDTO.class));
				}
			}catch (Exception e) {
				dataList.clear();
				log.error("map转对象失败！", e);
			}
		}
		return dataList;
	}
	
	/**
	 * 获取24小时逐小时天气预报
	 * @param location 城市标识
	 * @return
	 */
	public static List<Map<String, Object>> getHour24Predict(String location) {
		List<Map<String, Object>> hourDataArray = new ArrayList<Map<String, Object>>();
		
		Map<String, Object> dataMap = getHour24PredictWithLocation(location);
		if(!dataMap.containsKey("hourly")) {
			hourDataArray = (List<Map<String, Object>>) dataMap.get("hourly");
		}
		
		return hourDataArray;
	}
	
	/**
	 * 获取24小时逐小时天气预报
	 * @param location
	 * @return 
	 * 
	* {
	* 	"location": {
	* 		"id": "WX4FBXXFKE4F",
	* 		"name": "北京",
	* 		"country": "CN",
	* 		"path": "北京,北京,中国",
	* 		"timezone": "Asia/Shanghai",
	* 		"timezone_offset": "+08:00"
	* 	},
	* 	"hourly": [
	* 		{
	* 			"time": "2021-02-07T11:00:00+08:00",
	* 			"text": "晴",
	* 			"code": "0",
	* 			"temperature": "2",
	* 			"humidity": "24",
	* 			"wind_direction": "北",
	* 			"wind_speed": "10"
	* 		}
	* 	]
	* } 
	 * 
	 */
	public static Map<String, Object> getHour24PredictWithLocation(String location) {
		Map<String, Object> dataItem = new HashMap<>();
		
		String url = Const.ServiceURL.hour24Predict;
		url = url.replace(Const.LOCATION, location);
		try {
			String result = HttpUtil.get(url);
			Const.requestAdd(Const.API.hour24Predict);
			Map<String, Object> resultMap = SystemConstant.jsonMapper.readValue(result, Map.class);
			List<Map<String, Object>> resultArray = (List<Map<String, Object>>) resultMap.get("results");
			dataItem = resultArray.get(0);
		}catch (Exception e) {
			log.error("查询逐日天气预报和昨日天气数据失败！location="+location, e);
		}
		
		return dataItem;
	}
	
	/**
	 * 获取24小时逐小时天气预报
	 * @param location 城市标识
	 * @return
	 */
	public static List<Hour24PredictDTO> getHour24PredictObj(String location) {
		List<Hour24PredictDTO> hourDataList = new ArrayList<>();
		
		List<Map<String, Object>> hourDataMapList = getHour24Predict(location);
		if(!hourDataMapList.isEmpty()) {
			try {
				for(Map<String, Object> map : hourDataMapList) {
					hourDataList.add(map2Obj(map, Hour24PredictDTO.class));
				}
			}catch (Exception e) {
				hourDataList.clear();
				log.error("map转对象失败！", e);
			}
		}
		
		return hourDataList;
	}
	
	/**
	 * 获取过去24小时历史天气
	 * @param location
	 * @return
	 */
	public static List<Map<String, Object>> getHour24History(String location) {
		List<Map<String, Object>> hourDataArray = new ArrayList<Map<String, Object>>();
		
		String url = Const.ServiceURL.hour24History;
		url = url.replace(Const.LOCATION, location);
		try {
			String result = HttpUtil.get(url);
			Const.requestAdd(Const.API.hour24History);
			Map<String, Object> resultMap = SystemConstant.jsonMapper.readValue(result, Map.class);
			List<Map<String, Object>> resultArray = (List<Map<String, Object>>) resultMap.get("results");
			Map<String, Object> dataItem = resultArray.get(0);
			hourDataArray = (List<Map<String, Object>>) dataItem.get("hourly_history");
		}catch (Exception e) {
			log.error("获取过去24小时历史天气数据失败！location="+location, e);
		}
		
		return hourDataArray;
	}
	
	/**
	 * 获取过去24小时历史天气
	 * @param location
	 * @return
	 */
	public static List<NowWeatherDTO> getHour24HistoryObj(String location) {
		List<NowWeatherDTO> dataList = new ArrayList<>();
		
		List<Map<String, Object>> dataMapList = getHour24History(location);
		if(!dataMapList.isEmpty()) {
			try {
				for(Map<String, Object> map : dataMapList) {
					dataList.add(map2Obj(map, NowWeatherDTO.class));
				}
			}catch (Exception e) {
				dataList.clear();
				log.error("map转对象失败！", e);
			}
		}
		
		return dataList;
	}
	
	/**
	 * 获取气象灾害预警信息
	 * @return
	 */
	public static List<Map<String, Object>> getAlarms() {
		List<Map<String, Object>> dataList = new ArrayList<Map<String, Object>>();
		try {
			String result = HttpUtil.get(Const.ServiceURL.alarm);
			Const.requestAdd(Const.API.alarm);
			Map<String, Object> resultMap = SystemConstant.jsonMapper.readValue(result, Map.class);
			List<Map<String, Object>> resultArray = (List<Map<String, Object>>) resultMap.get("results");
			for(Map<String, Object> dataItem : resultArray) {
				Map<String, Object> location = (Map<String, Object>) dataItem.get("location");
				List<Map<String, Object>> alarmArray = (List<Map<String, Object>>) dataItem.get("alarms");
				for(Map<String, Object> alarmItem : alarmArray) {
					alarmItem.putAll(location);
					dataList.add(alarmItem);
				}
			}
			
		}catch (Exception e) {
			log.error("获取气象灾害预警数据失败！", e);
		}
		
		return dataList;
	}
	
	/**
	 * 获取气象灾害预警信息
	 * @return [预警信息对象] 或 空集合
	 */
	public static List<AlarmDTO> getAlarmObjs() {
		List<AlarmDTO> resultList = new ArrayList<>();
		
		List<Map<String, Object>> alarmListMap = getAlarms();
		if(!alarmListMap.isEmpty()) {
			try {
				for(Map<String, Object> map : alarmListMap) {
					resultList.add(map2Obj(map, AlarmDTO.class));
				}
			}catch (Exception e) {
				resultList.clear();
				log.error("map转对象失败！", e);
			}
		}
		
		return resultList;
	}
	
	@SuppressWarnings("unused")
	private static <T extends WeatherResponseDTO> T map2Obj(Map<String, Object> map, Class<T> clz) throws Exception {
		T t = clz.newInstance();
		
		for(String key : map.keySet()) {
			Method m = null;
			try {
				m = clz.getMethod("set"+key.substring(0,1).toUpperCase()+key.substring(1), String.class);
			}catch (Exception e) {
			}
			if(m != null) {
				m.invoke(t, map.get(key));
			}
		}
		
		return t;
	}
	
	public static void main(String[] args) {
		getHour24HistoryObj("WW8P3NH2TPDT");
		System.out.println();
	}
}
