package com.smppw.utils;

import com.smppw.common.pojo.dto.CompoundRet;
import com.smppw.common.pojo.dto.DateValue;
import com.smppw.common.pojo.enums.Frequency;
import com.smppw.common.pojo.enums.NavType;
import org.joda.time.DateTime;

import java.util.*;
import java.util.Map.Entry;

/**
 * @author zhengsongliang
 * @datetime 2017年7月5日 下午5:03:42
 */
public class RateConvertorUtils {
	public static <V> Map<String, Map<String, V>> seperateSingleItemById(List<Map<String, V>> initList, String idName) {
		Map<String, Map<String, V>> map = new HashMap<>();
		for (Map<String, V> item : initList) {
			map.put(item.get("fund_id").toString(), item);
		}
		return map;
	}

	public static List<CompoundRet> convert2Obj(String secId, List<Map<String, Object>> secRets) {
		List<CompoundRet> values = new ArrayList<>();
		int n = secRets.size();
		for (int i = 0; i < n; i++) {
			Map<String, Object> map = secRets.get(i);
			String fundId = (String) map.get("fund_id");
			Double ret = CommonUtil.object2Double(map.get("ret_range"));
			String endDate = (String) map.get("end_date");
			if (fundId.equals(secId)) {
				CompoundRet value = new CompoundRet();
				value.setEndDate(endDate);
				value.setRetOfFund(ret);
				values.add(value);
			}
		}
		return values;
	}

	public static List<CompoundRet> convert2Obj(Map<String, Double> retDvs) {
		List<CompoundRet> values = new ArrayList<>();
		for (Entry<String, Double> entry : retDvs.entrySet()) {
			CompoundRet value = new CompoundRet();
			value.setEndDate(entry.getKey());
			value.setRetOfFund(entry.getValue());
			values.add(value);
		}
		return values;
	}

	public static List<CompoundRet> convert2Obj(List<CompoundRet> values, List<Map<String, Object>> bmkRfRets,
			String benchmarkId, String riskOfFreeId, Double riskOfFreeValue, String strategyId) {
		Map<String, CompoundRet> temp = new HashMap<>();
		for (CompoundRet value : values) {
			temp.put(value.getEndDate(), value);
		}
		int n = bmkRfRets.size();
		for (int i = 0; i < n; i++) {
			Map<String, Object> map = bmkRfRets.get(i);
			String fundId = (String) map.get("fund_id");
			Double ret = CommonUtil.object2Double(map.get("ret_range"));
			String endDate = (String) map.get("end_date");
			if (temp.containsKey(endDate)) {
				if (fundId.equals(benchmarkId))
					temp.get(endDate).setRetOfBmk(ret);
				else if (strategyId != null && fundId.equals(strategyId))
					temp.get(endDate).setRetOfStg(ret);
				else if (fundId.equals(riskOfFreeId)) {
					temp.get(endDate).setRetOfRf(ret);
				}
				if (riskOfFreeId == null && riskOfFreeValue != null)
					temp.get(endDate).setRetOfRf(riskOfFreeValue / 12);
			}

		}

		values = new ArrayList<>(temp.values());
		Collections.sort(values, new Comparator<CompoundRet>() {

			@Override
			public int compare(CompoundRet o1, CompoundRet o2) {
				return o1.getEndDate().compareTo(o2.getEndDate());
			}

		});
		return values;
	}





	public static Map<String, List<Map<String, Object>>> seperateListById(List<String> secIds,
			List<Map<String, Object>> initDataList, String valueName) {
		Map<String, List<Map<String, Object>>> map = seperateListById(initDataList, valueName);
		for (String secId : secIds) {
			if (!map.containsKey(secId)) {
				map.put(secId, new ArrayList<>());
			}
		}
		return map;
	}

	public static <V> Map<String, List<Map<String, V>>> seperateListById(List<Map<String, V>> initList, String idName) {
		Map<String, List<Map<String, V>>> resMap = new HashMap<>();

		int n = initList.size();
		for (int i = 0; i < n; i++) {
			Map<String, V> unit = initList.get(i);
			if (unit == null)
				continue;
			String id = (String) unit.get(idName);
			if (!resMap.containsKey(id))
				resMap.put(id, new ArrayList<>());
			resMap.get(id).add(unit);
		}
		return resMap;
	}

	public static Map<String, List<DateValue>> convertNavList(List<Map<String,Object>> initRetList, Frequency dataSource, NavType navType) {

		switch (navType) {
			case WithdrawalNav:
				return convertNavList(initRetList, dataSource, "cumulative_nav_withdrawal");

			case OriginalNav:
				return convertNavList(initRetList, dataSource, "original_nav");

			default:
				return convertNavList(initRetList, dataSource, "cumulative_nav");
		}

	}

	public static <T> Map<String, List<DateValue>> convertNavList(List<Map<String, T>> initRetList,
																  Frequency dataSource, String navKey) {
		Map<String, List<DateValue>> map = new HashMap<>();
		String dataSourceKey = dataSource.getShortName() + "_nav";
		for (Map<String, T> unit : initRetList) {
			if (unit != null) {
				String id = unit.get("fund_id").toString();
				if (!map.containsKey(id)) {
					map.put(id, new ArrayList<>());
				}
				if (!unit.containsKey(dataSourceKey)
						|| unit.get(dataSourceKey).toString().equals("1") && unit.get(navKey) != null) {
					map.get(id).add(new DateValue(unit.get("price_date").toString(),
							CommonUtil.string2Double(unit.get(navKey).toString())));
				}
			}
		}
		for (List<DateValue> dvs : map.values()) {
			Collections.sort(dvs);
		}

		return map;
	}

	public static Map<String, Map<String, Object>> getIdValueMap(String startDate, String endDate, Map<String, List<DateValue>> navMap, Frequency dataSource) {
		Map<String, Map<String, Object>> idDateValueMap = new HashMap<>();
		for (String secId : navMap.keySet()) {
			List<DateValue> validNavList = navMap.get(secId);
			List<DateValue> values = new ArrayList<>();
			for(DateValue dv : validNavList){
				if(startDate.equals(dv.getDate()) || endDate.equals(dv.getDate()) || (DateTime.parse(dv.getDate()).isAfter(DateTime.parse(startDate)) && DateTime.parse(dv.getDate()).isBefore(DateTime.parse(endDate)))){
					values.add(dv);
				}
			}
			Map<String, Object> dateValueMap = convert2Map(values);
			idDateValueMap.put(secId, dateValueMap);
		}
		return idDateValueMap;
	}

	private static Map<String, Object> convert2Map(List<DateValue> validNavList) {
		Map<String, Object> map = new HashMap<>();
		for (DateValue dv : validNavList) {
			map.put(dv.getDate(), dv.getValue());
		}
		return map;
	}


	public static <T> Map<String, Map<String, Double>> transfer2TwoDimensionMap(List<Map<String, T>> initRetList,
																				String firstKey, String secondKey, String valueKey) {
		Map<String, Map<String, Double>> map = new TreeMap<>();
		for (Map<String, T> unit : initRetList) {
			if (unit != null) {
				String id = unit.get(firstKey).toString();
				if (!map.containsKey(id)) {
					map.put(id, new TreeMap<String, Double>());
				}
				T t = unit.get(valueKey);
				if (t == null) {
					continue;
				}
				map.get(id).put(unit.get(secondKey).toString(), Double.valueOf(unit.get(valueKey).toString()));
			}

		}
		return map;
	}
}
