package com.persagy.framework.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
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 org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import com.persagy.core.constant.SystemConstant;
import com.persagy.framework.dto.WeatherItemConfig;
import com.persagy.framework.dto.WeatherItemDTO;
import com.persagy.functions.weather.dto.CityDTO;

@SuppressWarnings("unchecked")
public class ConfigUtil {
	private static final Logger LOGGER = Logger.getLogger(ConfigUtil.class);

	private static String specialCity = "北京市,天津市,上海市,重庆市";

	/** 龙湖定制所需要的进行5min天气数据记录的城市名称集合 */
	private static Map<String, String> longHuCity = new HashMap<String, String>();
	/** {城市数据字典编码:城市DTO} */
	private static Map<String, CityDTO> dicCode2City = new HashMap<String, CityDTO>();
	/** {城市区县数据字典名称:唯一城市数据字典编码} */
	private static Map<String, String> dicName2DicCode = new HashMap<String, String>();
	/** {城市区县数据字典名称:城市数据字典编码1,城市数据字典编码2...} */
	private static Map<String, String> dicName2MoreDicCode = new HashMap<String, String>();
	/** {城市区县数据字典名称:城市ID} */
	private static Map<String, String> dicName2CityId = new HashMap<String, String>();
	/** {第三方城市名称:城市ID} */
	private static Map<String, String> cityName2CityId = new HashMap<String, String>();
	/** {城市区县数据字典编码:城市ID} */
	private static Map<String, String> dicCode2CityId = new HashMap<String, String>();
	/** 需要进行小时天气记录的城市ID */
	private static Set<String> hourCitySet = new HashSet<>();
	/** 第三方天气服务支持城市信息{城市ID码:城市信息} */
	private static Map<String, CityDTO> id2City = new HashMap<String, CityDTO>();
	/** 万达用到的城市{数据字典城市编码:城市名称} */
	private static Map<String, String> wandaCity = new HashMap<String, String>();
	/** 气象指标配置信息 */
	private static WeatherItemConfig weatherItemConfig = new WeatherItemConfig();

	public static List<Map<String, String>> getAllThread() {
		List<Map<String, String>> tList = new ArrayList<>();
		try {
			Set<Thread> threads = Thread.getAllStackTraces().keySet();
			if(null != threads) {
				for(Thread t : threads) {
					Map<String, String> map = new HashMap<>();
					map.put("id", t.getId()+"");
					map.put("name", t.getName()+"");
					map.put("priority", t.getPriority()+"");
					map.put("state", t.getState()+"");
					tList.add(map);
				}
			}
		} catch (Exception e) {
		}
		return tList;
	}

	public static Map<String, String> getCityName2CityId() {
		return cityName2CityId;
	}

	/**
	 * 根据数据字典城市名称获取第三方天气服务城市id
	 * @param name
	 * @return
	 */
	public static String getCityIdByDicName(String name) {
		String dicCode = dicName2DicCode.get(name);
		return dicCode2CityId.get(dicCode);
	}

	/**
	 * 根据数据字典城市编码获取第三方天气服务城市id
	 * @param dicCode
	 * @return
	 */
	public static String getCityIdByDicCode(String dicCode) {
		return dicCode2CityId.get(dicCode);
	}

	/**
	 * 获取 {城市区县数据字典名称:城市ID}
	 * @return
	 */
	public static Map<String, String> getDicName2CityId() {
		return dicName2CityId;
	}
	/**
	 * 获取 {城市区县数据字典编码:城市ID}
	 * @return
	 */
	public static Map<String, String> getDicCode2CityId() {
		return dicCode2CityId;
	}
	/**
	 * 获取需要进行小时天气记录的城市ID集合
	 * @return
	 */
	public static Set<String> getHourCitySet() {
		return hourCitySet;
	}
	/**
	 * 第三方天气服务支持城市信息{城市ID码:城市信息}
	 * @return
	 */
	public static Map<String, CityDTO> getId2City() {
		return id2City;
	}


	private static Map<String, String> getCityNamesOf5Min() {
		try {
			Map<String, String> cities = getConfigMap("/config/business/longhuConfig.json", Map.class);
			LOGGER.info("读取longhuConfig.json配置成功，加载数据记录数："+cities.size());
			return cities;
		}catch (Exception e) {
			LOGGER.error("读取longhuConfig.json配置失败！！！");
			e.printStackTrace();
		}
		return new HashMap<String, String>();
	}

	/**
	 * 获取龙湖定制配置信息：需要进行5min天气记录的城市
	 * @return {城市名称:城市id}集合， 可能为空集合
	 */
	public static Map<String, String> longHu5MinCitiesGet() {
		if(longHuCity.isEmpty()) {
			longHuCity = getCityNamesOf5Min();
		}
		return longHuCity;
	}

	public static Map<String, String> wandaCitiesGet() {
		if(wandaCity.isEmpty()) {
			try {
				initWandaCities();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		return wandaCity;
	}
	
	public static WeatherItemConfig weatherItemConfig() {
		if(weatherItemConfig.getItems().isEmpty()) {
			try {
				
			}catch (Exception e) {
				// TODO: handle exception
				e.printStackTrace();
			}
		}
		
		return weatherItemConfig;
	}

	/**
	 * 刷新龙湖定制配置信息，从新读取配置文件信息加载到缓存
	 */
	public static void cache_refresh_longhu() {
		LOGGER.info("refresh longhu config start....");
		Map<String, String> longHuCityNew = getCityNamesOf5Min();
		if(!longHuCityNew.isEmpty()) {
			synchronized (longHuCity) {
				longHuCity.clear();
				longHuCity.putAll(longHuCityNew);
			}
		}
		LOGGER.info("refresh longhu config end. load record : " + longHuCity.size());
	}

	/**
	 * 解析数据字典Geography.json文件
	 * @return {城市数据字典区域码:城市对象DTO}
	 */
	private static Map<String, CityDTO> analysisGeography() throws Exception {
		Map<String, CityDTO> result = new HashMap<String, CityDTO>();
		Map<String, Object> mapObj = getConfigMap("/config/business/Geography.json", Map.class);

		if(null != mapObj) {
			// 1解析直辖市
			List<Map<String, Object>> specialCities = mapObj.containsKey("specialCities")
					? (List<Map<String, Object>>) mapObj.get("specialCities")
					: null;
			if(null != specialCities) {
				for(Map<String, Object> spCity : specialCities) {
					if(spCity.containsKey("cityInfo")) {
						// 市信息

						List<Map<String, Object>> cityInfo = (List<Map<String, Object>>) spCity.get("cityInfo");

						for(Map<String, Object> cityItem : cityInfo) {
							if(cityItem.size() > 2) {
								String dicCode = cityItem.get("code")+"";
								if(!"null".equals(dicCode)) {
									CityDTO cityDto = new CityDTO();
									cityDto.setDicCode(dicCode);
									cityDto.setDicName(cityItem.get("name")+"");
									cityDto.setLatitude(cityItem.get("latitude")+"");
									cityDto.setLongitude(cityItem.get("longitude")+"");
									cityDto.setAltitude(cityItem.get("altitude")+"");
									result.put(dicCode, cityDto);
								}
							}
						}
					}

					if(spCity.containsKey("district")) {
						// 区县信息

						List<Map<String, Object>> district = (List<Map<String, Object>>) spCity.get("district");
						String dicCode = "null";
						for(Map<String, Object> cityItem : district) {
							dicCode = cityItem.get("code")+"";
							if(!dicCode.equals("null")) {
								CityDTO cityDto = new CityDTO();
								cityDto.setDicCode(dicCode);
								cityDto.setDicName(cityItem.get("districtName")+"");
								cityDto.setLatitude(cityItem.get("latitude")+"");
								cityDto.setLongitude(cityItem.get("longitude")+"");
								cityDto.setAltitude(cityItem.get("altitude")+"");
								result.put(dicCode, cityDto);
							}
						}
					}
				}
			}

			// 2解析普通省市
			List<Map<String, Object>> normalCities = mapObj.containsKey("normal")
					? (List<Map<String, Object>>) mapObj.get("normal")
					: null;
			if(null != normalCities) {
				for(Map<String, Object> nmCity : normalCities) {
					if(nmCity.containsKey("cities")) {
						List<Map<String, Object>> cities = (List<Map<String, Object>>) nmCity.get("cities");
						for(Map<String, Object> cityMap : cities) {
							// 市信息
							List<Map<String, Object>> cityInfoList = (List<Map<String, Object>>) cityMap.get("cityInfo");
							Map<String, Object> cityInfo = cityInfoList.get(0);

							String dicCode = cityInfo.get("code")+"";
							String cityName = cityInfo.get("name")+"";
							if(!dicCode.equals("null")) {
								CityDTO cityDto = new CityDTO();
								cityDto.setDicCode(dicCode);
								cityDto.setDicName(cityName);
								cityDto.setLatitude(cityInfo.get("latitude")+"");
								cityDto.setLongitude(cityInfo.get("longitude")+"");
								cityDto.setAltitude(cityInfo.get("altitude")+"");
								result.put(dicCode, cityDto);
							}

							List<Map<String, Object>> districtList = (List<Map<String, Object>>) cityMap.get("district");
							for(Map<String, Object> district : districtList) {
								dicCode = district.get("code") + "";
								if(dicCode.equals("null") || "市辖区".equals(district.get("districtName")+"")) {
									continue;
								}

								CityDTO districtCityDto = new CityDTO();
								districtCityDto.setDicCode(dicCode);
								districtCityDto.setDicName(district.get("districtName")+"");
								districtCityDto.setLatitude(district.get("latitude")+"");
								districtCityDto.setLongitude(district.get("longitude")+"");
								districtCityDto.setAltitude(district.get("altitude")+"");
								result.put(dicCode, districtCityDto);
							}
						}
					}
				}
			}
			LOGGER.info("读取Geography.json配置成功，加载数据记录数："+result.size());
		}

		return result;
	}

	/**
	 * 获取 {城市数据字典编码:城市DTO}
	 * @return
	 * @throws Exception
	 */
	public static Map<String, CityDTO> dicCityObjMap() throws Exception {
		if(dicCode2City.isEmpty()) {
			initDicCode2City();
		}

		return dicCode2City;
	}

	/**
	 * 读取Geography.json配置文件，刷新数据字典编码与数据字典城市信息映射关系
	 * @throws Exception
	 */
	private static void initDicCode2City() throws Exception{
		dicCode2City.clear();
		dicCode2City.putAll(analysisGeography());
	}

	/**
	 * 获取 {城市数据字典名称:唯一城市数据字典编码}
	 * @return
	 * @throws Exception
	 */
	public static Map<String, String> dicName2DicCodeMap() throws Exception {
		if(dicName2DicCode.isEmpty()) {
			initDicNameCodeRelationFromGeography();
		}
		return dicName2DicCode;
	}

	/**
	 * 获取 {城市数据字典名称:城市数据字典编码1,城市数据字典编码2...}
	 * @return
	 * @throws Exception
	 */
	public static Map<String, String> dicName2MoreDicCodeMap() throws Exception {
		if(dicName2MoreDicCode.isEmpty()) {
			initDicNameCodeRelationFromGeography();
		}
		return dicName2MoreDicCode;
	}

	/**
	 * 刷新Geography.json配置相关缓存
	 * @throws Exception
	 */
	public static void cache_refresh_geography() throws Exception {
		LOGGER.info("refresh geography config start....");
		initDicCode2City();
		initDicNameCodeRelationFromGeography();
		LOGGER.info("refresh geography config end. load record :" + dicCode2City.size());
	}

	/**
	 * 刷新cityListData.xlsx配置相关缓存
	 * @throws Exception
	 */
	public static void cache_refresh_cityexl() throws Exception {
		LOGGER.info("refresh cityDataList config start....");
		analysisCityListDataExl();
		LOGGER.info("refresh cityDataList config end. totalCity:" + id2City.size() + ", hourCity:"+hourCitySet.size());
	}

	public static void cache_refresh_wandact() throws Exception {
		LOGGER.info("refresh wandaCities config start...");
		initWandaCities();
		LOGGER.info("refresh wandaCities config end. cityNum: " + wandaCity.size());
	}
	
	public static void cache_refresh_weatherItem() throws Exception {
		LOGGER.info("refresh weatherItem config start...");
		initWeatherItemConfig();
		LOGGER.info("refresh weatherItem config end. itemsNum: " + weatherItemConfig.getItems().size());
	}

	private static void initWeatherItemConfig() {
		WeatherItemConfig wic = getConfigMap("/config/business/weatherItem.json", WeatherItemConfig.class);
		if(null != wic && wic.getItems() != null && wic.getItems().size() > 0) {
			weatherItemConfig = wic;
		}
	}

	/**
	 * 从Geography.json配置文件获取数据，刷新数据字典城市名称与城市编码对应关系
	 * @throws Exception
	 */
	private static void initDicNameCodeRelationFromGeography() throws Exception {
		Map<String, CityDTO> dicCityDtoMap = dicCityObjMap();

		Map<String, String> tempMap = new HashMap<>();
		String dicName= null;

		for(String dicCode : dicCityDtoMap.keySet()) {
			dicName = dicCityDtoMap.get(dicCode).getDicName();
			if(tempMap.containsKey(dicName)) {
				tempMap.put(dicName, dicCode+","+tempMap.get(dicName));
			}else {
				tempMap.put(dicName, dicCode);
			}
		}

		Map<String, String> forDicName2DicCode = new HashMap<>();
		Map<String, String> forDicName2MoreDicCode = new HashMap<>();
		for(String name : tempMap.keySet()) {
			if(tempMap.get(name).contains(",")) {
				forDicName2MoreDicCode.put(name, tempMap.get(name));
			}else {
				forDicName2DicCode.put(name, tempMap.get(name));
			}
		}

		dicName2DicCode.clear();
		dicName2DicCode.putAll(forDicName2DicCode);
		if(dicName2DicCode.isEmpty()) {
			dicName2DicCode.put("999999", null);
		}

		dicName2MoreDicCode.clear();
		dicName2MoreDicCode.putAll(forDicName2MoreDicCode);
		if(dicName2MoreDicCode.isEmpty()) {
			dicName2MoreDicCode.put("999999", null);
		}
	}

	/**
	 * 根据城市数据字典名称获取数据字典编码
	 * @param dicCityName 城市数据字典名称
	 * @return 数据字典城市区域码(若对应多个区域码则区域码用英文,隔开) 或 null
	 */
	public static String dicCodeGet(String dicCityName) {
		String dicCode = null;
		try {
			dicCode = dicName2DicCodeMap().get(dicCityName);
			if(null == dicCode) {
				dicCode = dicName2MoreDicCodeMap().get(dicCityName);
			}
		}catch (Exception e) {
			e.printStackTrace();
		}

		return dicCode;
	}

	/**
	 * 读取json配置文件
	 * @param <T>
	 * @param filePath json文件路径，例如：/config/hello.json
	 * @param cls 反射Java类类型
	 * @return
	 * @throws Exception
	 */
	public static <T> T getConfigMap(String filePath, Class<T> cls) {
		try {
			URL url = ConfigUtil.class.getResource(filePath);
			T t = SystemConstant.jsonMapper.readValue(url, cls);
			return t;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 读取exl数据为字符集合
	 * @param filePath exl文件路径，例如：/config/hello.xlsx  /config/business/cityList.xlsx
	 * @param sheetIndex sheet也索引，从0开始
	 * @param rowStart 数据读取开始行，从0开始
	 * @param columnNum 每行读取数据的列数
	 * @return 二维字符集合[[]] 或 空数据集合 []
	 */
	public static List<String[]> getDataFromExl(String filePath, int sheetIndex, int rowStart, int columnNum) {
		List<String[]> resultList = new ArrayList<>();

		URL url = ConfigUtil.class.getResource(filePath);
		File file = new File(url.getFile());
		if(file.exists() && file.isFile()) {
			Workbook wb = null;
			FileInputStream fileInputStream = null;
			try {
				fileInputStream = new FileInputStream(file);
				wb = new XSSFWorkbook(fileInputStream);
				Sheet sheet = wb.getSheetAt(sheetIndex);
				int rowNum = sheet.getLastRowNum();
				if(rowStart < rowNum) {
					for(int rowIndex=rowStart; rowIndex<rowNum; rowIndex++) {
						Row rowNow = sheet.getRow(rowIndex);
						if (rowNow == null) {
							break;
						}

						String[] rowData = new String[columnNum];
						for(int columnIndex=0; columnIndex<columnNum; columnIndex++) {
							String cvalue = null;
							Cell cell = rowNow.getCell(columnIndex);
							if(null == cell) {
								continue;
							}
							try {
								cvalue = cell.getStringCellValue();
							}catch (IllegalStateException e) {
								cvalue = cell.getNumericCellValue()+"";
							}
							rowData[columnIndex] = cvalue;
						}
						resultList.add(rowData);
					}
				}
			}catch (Exception e) {
				resultList.clear();
				e.printStackTrace();
			}finally {
				if(null != fileInputStream) {
					try {
						fileInputStream.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
			if(wb != null) {
				try {
					wb.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		return resultList;
	}

	/**
	 * 字符串二位集合数据写入exl
	 * @param filePath exl路径
	 * @param sheetIndex sheet页索引
	 * @param rowStart 写入数据开始行
	 * @param dataList 数据
	 * @return
	 */
	public static boolean writeDataToExl(String filePath, int sheetIndex, int rowStart, List<String[]> dataList) {
		boolean result = false;

		URL url = ConfigUtil.class.getResource(filePath);
		File file = new File(url.getFile());

		FileOutputStream fileOutputStream = null;
		Workbook workbook = null;
		try {
			fileOutputStream = new FileOutputStream(file);
			workbook = new SXSSFWorkbook();

			Sheet sheet = workbook.createSheet("data");

			int rowNum = rowStart;
			for(String[] dataAry : dataList) {
				Row row = sheet.createRow(rowNum++);

				int cellNum = 0;
				for(String data : dataAry) {
					row.createCell(cellNum++).setCellValue(data == null ? "" : data);
				}
			}

			workbook.write(fileOutputStream);
			fileOutputStream.flush();
			result = true;
		}catch (Exception e) {
			e.printStackTrace();
		}finally {
			if(fileOutputStream != null) {
				try {
					fileOutputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if(workbook != null) {
				try {
					workbook.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		return result;
	}

	public static void cityListDataGet() throws Exception {
		List<String[]> dataList = getDataFromExl("/config/business/cityList.xlsx", 0, 1, 5);

		Map<String, String> dicNameCode = dicName2DicCodeMap();

		List<String[]> dataListCompare = new ArrayList<>();
		for(String[] cityInfo : dataList) {
			String[] cityInfoSuper = Arrays.copyOf(cityInfo, 9);
			dataListCompare.add(cityInfoSuper);

			if("yes".equals(cityInfo[4])) {
				String belong = cityInfo[1];
				belong = belong.contains("/") ? belong.substring(belong.lastIndexOf("/")+1) : belong;

				String shorName = cityInfo[2];
				shorName = shorName.contains("/") ? shorName.substring(shorName.lastIndexOf("/")+1) : shorName;

				if(dicNameCode.containsKey(belong)) {
					cityInfoSuper[5] = dicNameCode.get(belong);
					cityInfoSuper[6] = belong;
				}

				if(dicNameCode.containsKey(shorName)) {
					cityInfoSuper[7] = dicNameCode.get(shorName);
					cityInfoSuper[8] = shorName;
				}
			}
		}

		System.out.println(writeDataToExl("/config/business/cityList.xlsx", 2, 0, dataListCompare));
	}

	private static void initWandaCities() throws Exception {
		List<String[]> dataList = getDataFromExl("/config/business/WandaCityCodeName.xlsx", 0, 1, 2);
		if(!dataList.isEmpty()) {
			wandaCity.clear();
			String cityCode = null, cityName = null;
			for(String[] rowData : dataList) {
				cityCode = rowData[0];
				cityName = rowData[1];
				if(null != cityCode && cityCode.trim().length() > 5 && cityName != null) {
					cityCode = cityCode.trim();
					cityCode = cityCode.length() > 6 ? cityCode.substring(0, 6) : cityCode;
					wandaCity.put(cityCode, rowData[1]);
				}
			}
		}
	}

	/**
	 * 解析配置文件cityListData.xlsx中的数据，清理数据字典城市名称，数据字典城市编码与城市ID码的关系
	 * @throws Exception
	 */
	private static void analysisCityListDataExl() throws Exception {
		List<String[]> dataList = getDataFromExl("/config/business/cityListData.xlsx", 0, 1, 7);

		String cityId = null;
		String dicCode = null;
		String dicName = null;
		String belong = null;
		String name = null;
		String pinyin = null;

		Map<String, CityDTO> forId2City = new HashMap<>();
		Set<String> forHourCitySet = new HashSet<>();
		Map<String, String> forDicName2CityId = new HashMap<String, String>();
		Map<String, String> forDicCode2CityId = new HashMap<String, String>();
		Map<String, String> forCityName2CityId = new HashMap<String, String>();
		Set<String> repeatNameSet = new HashSet<String>();

		for(String[] record : dataList) {
			cityId = record[0];
			belong = record[1];
			name = record[2];
			pinyin = record[3];
			dicCode = record[5];
			dicName = record[6];

			if ((cityId != null) && (cityId.trim().length() != 0)) {
				String cityName = name;
				if (cityName != null) {
					if (cityName.contains("/")) {
						cityName = cityName.substring(cityName.lastIndexOf("/") + 1);
					}
					if (forCityName2CityId.containsKey(cityName)) {
						repeatNameSet.add(cityName);
					}
					forCityName2CityId.put(cityName, cityId);
				}

				CityDTO dto = new CityDTO(cityId, name, belong, pinyin, dicCode, dicName);
				forId2City.put(cityId, dto);

				if("yes".equals(record[4])) {
					forHourCitySet.add(cityId);
				}

				if(dicName != null) {
					forDicName2CityId.put(dicName, cityId);
				}

				if(dicCode != null) {
					if(dicCode.contains(",")) {
						for(String dicCodeItem : dicCode.split(",")) {
							forDicCode2CityId.put(dicCodeItem, cityId);
						}
					}else {
						forDicCode2CityId.put(dicCode, cityId);
						if(dicName != null && (dicName.endsWith("市") || dicName.endsWith("自治州")) && !specialCity.contains(dicName)) {
							if(dicCode.endsWith("00")) {
								forDicCode2CityId.put(dicCode.substring(0, dicCode.length()-2)+"01", cityId);
							}else if(dicCode.endsWith("01")) {
								forDicCode2CityId.put(dicCode.substring(0, dicCode.length()-2)+"00", cityId);
							}
						}
					}
				}
			}

		}

		id2City.clear();
		id2City.putAll(forId2City);

		hourCitySet.clear();
		hourCitySet.addAll(forHourCitySet);

		dicName2CityId.clear();
		dicName2CityId.putAll(forDicName2CityId);

		if (!repeatNameSet.isEmpty()) {
			for (String cityName : repeatNameSet) {
				forCityName2CityId.remove(cityName);
			}
		}
		cityName2CityId.clear();
		cityName2CityId.putAll(forCityName2CityId);

		String newKey = null;
		Map<String, String> forDicCode2CityIdSuper = new HashMap<>(forDicCode2CityId);
		for(String key : forDicCode2CityId.keySet()) {
			if(key != null && key.length()==6 && (key.endsWith("02") || key.endsWith("03"))) {
				if(key.endsWith("00") || key.endsWith("01")) {
					forDicCode2CityIdSuper.put(key.substring(0, 4) + "01", forDicCode2CityId.get(key));
					forDicCode2CityIdSuper.put(key.substring(0, 4) + "00", forDicCode2CityId.get(key));
				}else if(key.endsWith("02") || key.endsWith("03")) {
					newKey = key.substring(0, 4) + "00";
					if(!forDicCode2CityIdSuper.containsKey(newKey)) {
						forDicCode2CityIdSuper.put(newKey, forDicCode2CityId.get(key));
					}
					newKey = key.substring(0, 4) + "01";
					if(!forDicCode2CityIdSuper.containsKey(newKey)) {
						forDicCode2CityIdSuper.put(newKey, forDicCode2CityId.get(key));
					}
				}
			}
		}
		dicCode2CityId.clear();
		dicCode2CityId.putAll(forDicCode2CityIdSuper);
	}

	public static String getComputeStr(String str) {
		str = str == null ? "" : str;

		str = str + "www.persagy.com";

		int hashInt = Math.abs(str.hashCode());

		hashInt = 100000 + hashInt % 103;
		String hashStr = ("" + hashInt).substring(3);

		return hashStr;
	}

	public static String getDayHisSuffix(String str) {
		str = str == null ? "" : str;

		str = str + "www.persagy.com";

		int hashInt = Math.abs(str.hashCode());

		hashInt = 1000 + hashInt % 10;
		String hashStr = ("" + hashInt).substring(2);

		return hashStr;
	}

	public static String getLocation(String name, String dicCode, String projectId) {
		String location = getLocationStrict(name, dicCode, projectId);

		if(location == null) {
			location = name;
		}

		return location;
	}

	/**
	 * 匹配顺序1.使用城市编码（项目id解析出城市编码）做精确匹配;2.按名称精确匹配;3.按数据字典名称模糊匹配;4.按第三方城市名称模糊匹配
	 * @param name
	 * @param dicCode
	 * @param projectId
	 * @return null或城市编码
	 */
	public static String getLocationStrict(String name, String dicCode, String projectId) {
		if(dicCode == null && projectId != null && projectId.length() > 8) {
			dicCode = projectId.substring(2, 8);
		}

		String location = null;

		if(null != dicCode) {
			location = dicCode2CityId.get(dicCode);
		}

		if(location == null && dicName2CityId.containsKey(name)) {
			return dicName2CityId.get(name);
		}

		if (location == null && cityName2CityId.containsKey(name)) {
			return  cityName2CityId.get(name);
		}

		if(location == null && name != null) {
			for(String dicName : dicName2CityId.keySet()) {
				if(dicName.startsWith(name)) {
					return dicName2CityId.get(dicName);
				}
			}

			for(String cityName : cityName2CityId.keySet()) {
				if(name.startsWith(cityName)) {
					return cityName2CityId.get(cityName);
				}
			}
		}

		return location;
	}

	public static String getHourCity(String name, String dicCode, String projectId) {
		String location = getLocationStrict(name, dicCode, projectId);
		if (hourCitySet.contains(location)) {
			return location;
		}
		return null;
	}

	public static String getHourLocation(String name, String dicCode, String projectId) {
		String location = getLocationStrict(name, dicCode, projectId);
		return hourCitySet.contains(location) ? location : null;
	}

	public static void cache_refresh_all() throws Exception {
		cache_refresh_longhu();
		cache_refresh_geography();
		cache_refresh_cityexl();
		cache_refresh_wandact();
		cache_refresh_weatherItem();
	}

	public static void main(String[] args) throws Exception {
		WeatherItemConfig wic = getConfigMap("/config/business/weatherItem.json", WeatherItemConfig.class);
		
		Map<String, List<String>> map = new HashMap<>();
		for(WeatherItemDTO item : wic.getItems()) {
			for(String type : item.getDataTypeBelong()) {
				if(map.containsKey(type)) {
					map.get(type).add(item.getName());
				}else {
					map.put(type, new ArrayList<>(Arrays.asList(item.getName())));
				}
			}
		}
		
		for(String type : map.keySet()) {
			System.out.println(type+": "+map.get(type));
		}
		/*
		List<String> list = FileTools.readFileToList(new File("D:/wz/wanda.txt"));
		for(String city : list) {
			String cityCode = getHourCity(null, city, null);
			if(null == cityCode) {
				cityCode = getHourCity(null, city.substring(0, 4) + "00", null);
			}
			System.out.println(city + "=" + cityCode);
		}
		*/
	}
}
