package com.persagy.functions.weather.business.v2020;

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

import org.springframework.stereotype.Service;

import com.persagy.core.service.BaseBusinessService;
import com.persagy.core.service.BusinessService;
import com.persagy.framework.util.ConfigUtil;
import com.persagy.framework.util.DateUtils;
import com.persagy.framework.util.SunComputeUtil;
import com.persagy.functions.weather.constant.Const;
import com.persagy.functions.weather.constant.ConstTime;
import com.persagy.functions.weather.dto.CityDTO;

@Service("SunRiseAndSet")
@SuppressWarnings({ "unchecked", "rawtypes" })
public class SunRiseAndSet extends BaseBusinessService<Map> implements BusinessService {

	@Override
	public void handle(Map dto, List content) throws Exception {
		
		Map<String, Object> paramMap = analysisParam(dto);
		Date dayStart = (Date) paramMap.get("dayStart");
		Date dayEnd = (Date) paramMap.get("dayEnd");
		Double longitude = (Double) paramMap.get("longitude");
		Double latitude = (Double) paramMap.get("latitude");
		
		Date dayIndex = dayStart;
		do {
			Map<String, Object> item = new HashMap<>();
			item.put("sunRise", SunComputeUtil.getSunrise(longitude, latitude, dayIndex));
			item.put("sunSet", SunComputeUtil.getSunset(longitude, latitude, dayIndex));
			content.add(item);
			dayIndex = DateUtils.getDayOff(dayIndex, 1);
		}while(dayIndex.before(dayEnd));
	}

	private Map<String, Object> analysisParam(Map dto) throws Exception {
		Map<String, Object> result = new HashMap<>();
		
		String cityName = (String) dto.get("cityName");
		String cityCode = (String) dto.get("cityCode");
		String projectId = (String) dto.get("projectId");
		Double longitude = (Double) dto.get("longitude");
		Double latitude = (Double) dto.get("latitude");
		String startDay = (String) dto.get("startDay");
		String endDay = (String) dto.get("endDay");
		
		if(null == cityName && cityCode == null && projectId == null && longitude == null && latitude == null) {
			throw new Exception(Const.ErrorTag.paramMis);
		}
		
		if(null != cityCode && cityCode.length() != 6) {
			throw new Exception(Const.ErrorTag.paramUnrecognized + " : cityCode="+cityCode);
		}
		
		if(null != projectId && projectId.length() != 12) {
			throw new Exception(Const.ErrorTag.paramUnrecognized + " : projectId="+projectId);
		}
		
		if((longitude != null) ^ (latitude != null)) {
			throw new Exception(Const.ErrorTag.paramMis + " longitude or latitude");
		}
		
		if(null == startDay || endDay == null || startDay.length() != 10 || endDay.length() != 10) {
			throw new Exception(Const.ErrorTag.paramUnrecognized + " startDay or endDay");
		}
		
		Date dayStart = DateUtils.str2Date(startDay, DateUtils.SDF_DAY);
		Date dayEnd = DateUtils.str2Date(endDay, DateUtils.SDF_DAY);
		
		if(dayStart.after(dayEnd)) {
			throw new Exception(Const.ErrorTag.paramValueError + " : startDay, endDay");
		}
		
		long tspan = dayEnd.getTime() - dayStart.getTime();
		if(tspan > ConstTime.ms_year) {
			throw new Exception(Const.ErrorTag.timeToLong);
		}
		
		result.put("dayStart", dayStart);
		result.put("dayEnd", dayEnd);
		
		if(longitude != null) {
			result.put("longitude", longitude);
			result.put("latitude", latitude);
		}else {
			CityDTO cityInfo = ConfigUtil.dicCityObjMap().get(cityCode);
			if(null == cityInfo && projectId != null) {
				cityInfo = ConfigUtil.dicCityObjMap().get(projectId.substring(2, 8));
			}
			
			if(null == cityInfo && cityName != null) {
				cityInfo = ConfigUtil.dicCityObjMap().get(ConfigUtil.dicName2DicCodeMap().get(cityName));
				
				if(null == cityInfo) {
					for(String name : ConfigUtil.dicName2DicCodeMap().keySet()) {
						if(name.startsWith(cityName) || cityName.startsWith(name)) {
							cityInfo = ConfigUtil.dicCityObjMap().get(ConfigUtil.dicName2DicCodeMap().get(name));
							break;
						}
					}
				}
			}
			
			if(null == cityInfo || cityInfo.getLongitude() == null || cityInfo.getLatitude() == null) {
				throw new Exception(Const.ErrorTag.cityUnsupport);
			}
			
			result.put("longitude", Double.parseDouble(cityInfo.getLongitude()));
			result.put("latitude", Double.parseDouble(cityInfo.getLatitude()));
		}
		
		return result;
	}
}
