/**
 * 
 */
package com.abm.mainet.brms.rest.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.abm.mainet.brms.core.constant.Constant;
import com.abm.mainet.brms.core.constant.MainetConstants;
import com.abm.mainet.brms.core.dto.LookUp;
import com.abm.mainet.brms.entity.ViewPrefixDetails;
import com.abm.mainet.brms.repository.PrefixDetailsRepository;
import com.abm.mainet.brms.rest.service.ILookUpService;

/**
 * @author Pranit.Mhatre
 * @since 26 November, 2013
 */
@Service
public class LookUpServiceImpl implements ILookUpService
{
	
	
	private LookUp									lookUp = new LookUp();
	
	private List<LookUp> 							lookUpList = new ArrayList<LookUp>(0);
	
	private Map<String, List<LookUp>> 				prefixMap = new LinkedHashMap<String, List<LookUp>>(0);
	
	private Map<Integer, List<LookUp>> 				lookUpMap = new LinkedHashMap<Integer, List<LookUp>>(0);
	
	private Map<String, Map<Integer, List<LookUp>>> hPrefixMap = new LinkedHashMap<String, Map<Integer, List<LookUp>>>(0);

	
	@Autowired
	private PrefixDetailsRepository prefixDetailsRepository;
	
	@Override
	@Transactional
	public Map<String, Object> getNonHirachicalPrefixDetails() {
		
		Map<Integer, Map<String, List<LookUp>>>		    	nonHirachicalDetailMap 	= new HashMap<Integer, Map<String, List<LookUp>>>(0);
		
		List<String>										nonHirachicalPrefix		= new ArrayList<String>(0);
		
		Map<String, Object> 								resultMap 				= new HashMap<>();
		
		loadNonHirachicalPrefix(nonHirachicalDetailMap,nonHirachicalPrefix);
		
		resultMap.put(MainetConstants.LookUp.NON_HIRACHICAL_DETAIL_MAP, nonHirachicalDetailMap);
		
		resultMap.put(MainetConstants.LookUp.NON_HIRACHICAL_LIST, nonHirachicalPrefix);
		
		return resultMap;
	}
	
	@Override
	@Transactional
	public Map<String, Object> getHirachicalPrefixDetails() {
		
		Map<Integer, Map<String, Map<Long,LookUp>>> 		hirachicalLevelMap 	 	= new LinkedHashMap<Integer, Map<String, Map<Long,LookUp>>>(0);
		
		Map<Integer,Map<String,Map<Integer,List<LookUp>>>> 	hirachicalDetailMap	  	= new HashMap<Integer,Map<String,Map<Integer,List<LookUp>>>>(0);
		
		List<String>										hirachicalPrefix 		= new ArrayList<String>(0);
		
		Map<String, Object> 								resultMap 				= new HashMap<>();
		
		loadHirachicalPrefix(hirachicalLevelMap,hirachicalDetailMap,hirachicalPrefix);
		
		resultMap.put(MainetConstants.LookUp.HIRACHICAL_LEVEL_MAP, hirachicalLevelMap);
		
		resultMap.put(MainetConstants.LookUp.HIRACHICAL_DETAIL_MAP, hirachicalDetailMap);
		
		resultMap.put(MainetConstants.LookUp.HIRACHICAL_LIST, hirachicalPrefix);
		
		return resultMap;
	}

	
	@Override
	public Map<String, Object> getAllPrefixDetails() {
		
		Map<Integer, Map<String, Map<Long,LookUp>>> 		hirachicalLevelMap 	 	= new HashMap<Integer, Map<String, Map<Long,LookUp>>>(0);
		
		Map<Integer,Map<String,Map<Integer,List<LookUp>>>> 	hirachicalDetailMap	  	= new HashMap<Integer,Map<String,Map<Integer,List<LookUp>>>>(0);
		
		Map<Integer, Map<String, List<LookUp>>>		    	nonHirachicalDetailMap 	= new HashMap<Integer, Map<String, List<LookUp>>>(0);
		
		List<String>										hirachicalPrefix 		= new ArrayList<String>(0);
		
		List<String>										nonHirachicalPrefix		= new ArrayList<String>(0);
		
		Map<String, Object> 								resultMap 				= new HashMap<>();
		
		loadHirachicalPrefix(hirachicalLevelMap,hirachicalDetailMap,hirachicalPrefix);

		loadNonHirachicalPrefix(nonHirachicalDetailMap,nonHirachicalPrefix);
		
		resultMap.put(MainetConstants.LookUp.HIRACHICAL_LEVEL_MAP, hirachicalLevelMap);
		
		resultMap.put(MainetConstants.LookUp.HIRACHICAL_DETAIL_MAP, hirachicalDetailMap);
		
		resultMap.put(MainetConstants.LookUp.NON_HIRACHICAL_DETAIL_MAP, nonHirachicalDetailMap);
		
		resultMap.put(MainetConstants.LookUp.HIRACHICAL_LIST, hirachicalPrefix);
		
		resultMap.put(MainetConstants.LookUp.NON_HIRACHICAL_LIST, nonHirachicalPrefix);
		
		return resultMap;
	}

	private void loadNonHirachicalPrefix(Map<Integer, Map<String, List<LookUp>>> nonHirachicalDetailMap, List<String> nonHirachicalPrefix) {
		
		List<ViewPrefixDetails> nPrefixDetails = new ArrayList<ViewPrefixDetails>(0);
		
		nPrefixDetails = getViewPrefixDetailsByType(MainetConstants.LookUp.NON_HIERARCHICAL);
		
		for (ViewPrefixDetails viewPrefixDetail : nPrefixDetails) 
		{
			if(!nonHirachicalPrefix.contains(viewPrefixDetail.getCpmPrefix()))
			{
				nonHirachicalPrefix.add(viewPrefixDetail.getCpmPrefix());
			}
			
			loadNonHirachicalDetailMap(viewPrefixDetail,nonHirachicalDetailMap);
		}
	}
	
	private void loadNonHirachicalDetailMap(ViewPrefixDetails viewPrefixDetails,Map<Integer, Map<String, List<LookUp>>> nonHirachicalDetailMap) {
		
		if(nonHirachicalDetailMap.containsKey(viewPrefixDetails.getOrgid().intValue()))
		{
			prefixMap = nonHirachicalDetailMap.get(viewPrefixDetails.getOrgid().intValue());
			
			if(prefixMap.containsKey(viewPrefixDetails.getCpmPrefix()))
			{
				lookUpList = prefixMap.get(viewPrefixDetails.getCpmPrefix());
				
				lookUp = new LookUp();
				lookUp.setLookUpId(viewPrefixDetails.getCodCpdId());
				lookUp.setLookUpCode(viewPrefixDetails.getCodCpdValue());
				lookUp.setDescLangFirst(viewPrefixDetails.getCodCpdDesc());
				lookUp.setDescLangSecond(viewPrefixDetails.getCodCpdDescMar());
				lookUp.setLookUpType(viewPrefixDetails.getCpmType());
				if(viewPrefixDetails.getCpdOthers() != null)
				{
					lookUp.setOtherField(viewPrefixDetails.getCpdOthers());
				}
				
				if(viewPrefixDetails.getCodCpdDefault()!= null && viewPrefixDetails.getCodCpdDefault().equals(MainetConstants.IsLookUp.STATUS.YES))
				{
					lookUp.setDefaultVal(viewPrefixDetails.getCodCpdDefault());
				}
				
				lookUpList.add(lookUp);
				
				prefixMap.put(viewPrefixDetails.getCpmPrefix(), lookUpList);
				
				nonHirachicalDetailMap.put(viewPrefixDetails.getOrgid().intValue(), prefixMap);
			}
			else
			{
				lookUpList = new ArrayList<LookUp>(0);
				
				lookUp = new LookUp();
				
				lookUp.setLookUpId(viewPrefixDetails.getCodCpdId());
				lookUp.setLookUpCode(viewPrefixDetails.getCodCpdValue());
				lookUp.setDescLangFirst(viewPrefixDetails.getCodCpdDesc());
				lookUp.setDescLangSecond(viewPrefixDetails.getCodCpdDescMar());
				lookUp.setLookUpType(viewPrefixDetails.getCpmType());
				
				if(viewPrefixDetails.getCpdOthers() != null)
				{
					lookUp.setOtherField(viewPrefixDetails.getCpdOthers());
				}
				
				if(viewPrefixDetails.getCodCpdDefault()!= null && viewPrefixDetails.getCodCpdDefault().equals(MainetConstants.IsLookUp.STATUS.YES))
				{
					lookUp.setDefaultVal(viewPrefixDetails.getCodCpdDefault());
				}
				lookUpList.add(lookUp);
				
				prefixMap.put(viewPrefixDetails.getCpmPrefix(), lookUpList);
				
				nonHirachicalDetailMap.put(viewPrefixDetails.getOrgid().intValue(), prefixMap);
			}
		}
		else
		{
			prefixMap = new HashMap<String, List<LookUp>>(0);
			
			lookUpList = new ArrayList<LookUp>(0);
			
			lookUp = new LookUp();
			
			lookUp.setLookUpId(viewPrefixDetails.getCodCpdId());
			lookUp.setLookUpCode(viewPrefixDetails.getCodCpdValue());
			lookUp.setDescLangFirst(viewPrefixDetails.getCodCpdDesc());
			lookUp.setDescLangSecond(viewPrefixDetails.getCodCpdDescMar());
			lookUp.setLookUpType(viewPrefixDetails.getCpmType());
			if(viewPrefixDetails.getCpdOthers() != null)
			{
				lookUp.setOtherField(viewPrefixDetails.getCpdOthers());
			}
			
			if(viewPrefixDetails.getCodCpdDefault()!= null && viewPrefixDetails.getCodCpdDefault().equals(MainetConstants.IsLookUp.STATUS.YES))
			{
				lookUp.setDefaultVal(viewPrefixDetails.getCodCpdDefault());
			}
			lookUpList.add(lookUp);
			
			prefixMap.put(viewPrefixDetails.getCpmPrefix(), lookUpList);
			
			nonHirachicalDetailMap.put(viewPrefixDetails.getOrgid().intValue(), prefixMap);
		}
	}

	private void loadHirachicalPrefix(Map<Integer, Map<String, Map<Long,LookUp>>> hirachicalLevelMap, Map<Integer, Map<String, Map<Integer, List<LookUp>>>> hirachicalDetailMap, List<String> hirachicalPrefix) {
		
		List<ViewPrefixDetails> hPrefixDetails = new ArrayList<ViewPrefixDetails>(0);
		
		hPrefixDetails = getViewPrefixDetailsByType(MainetConstants.LookUp.HIERARCHICAL);
		
		for (ViewPrefixDetails viewPrefixDetails : hPrefixDetails) {
				
			if(!hirachicalPrefix.contains(viewPrefixDetails.getCpmPrefix()))
			{
				hirachicalPrefix.add(viewPrefixDetails.getCpmPrefix());
			}
			
			loadHirachicalLevelMap(viewPrefixDetails,hirachicalLevelMap);
			
			loadHirachicalDetailMap(viewPrefixDetails,hirachicalDetailMap);
		}
	}

	private void loadHirachicalDetailMap(ViewPrefixDetails viewPrefixDetails,Map<Integer, Map<String, Map<Integer, List<LookUp>>>> hirachicalDetailMap) {

		if(hirachicalDetailMap.containsKey(viewPrefixDetails.getOrgid().intValue()))
		{
			hPrefixMap = hirachicalDetailMap.get(viewPrefixDetails.getOrgid().intValue());
			
			if(hPrefixMap.containsKey(viewPrefixDetails.getCpmPrefix()))
			{
				lookUpMap = hPrefixMap.get(viewPrefixDetails.getCpmPrefix());
				
				if(lookUpMap.containsKey(viewPrefixDetails.getComLevel()))
				{
					lookUpList = lookUpMap.get(viewPrefixDetails.getComLevel());
					
					lookUp 		= new LookUp();
					
					lookUp.setLookUpId(viewPrefixDetails.getCodCpdId());
					lookUp.setLookUpCode(viewPrefixDetails.getCodCpdValue());
					lookUp.setDescLangFirst(viewPrefixDetails.getCodCpdDesc());
					lookUp.setDescLangSecond(viewPrefixDetails.getCodCpdDescMar());
					lookUp.setLookUpType(viewPrefixDetails.getCpmType());
					if(viewPrefixDetails.getCodCpdDefault()!= null && viewPrefixDetails.getCodCpdDefault().equals(MainetConstants.IsLookUp.STATUS.YES))
					{
						lookUp.setDefaultVal(viewPrefixDetails.getCodCpdDefault());
					}
					if(viewPrefixDetails.getCodCpdParentId() != null)
					{
						lookUp.setLookUpParentId(viewPrefixDetails.getCodCpdParentId());
					}
					
					lookUpList.add(lookUp);
					
					lookUpMap.put(viewPrefixDetails.getComLevel(), lookUpList);
					
					hPrefixMap.put(viewPrefixDetails.getCpmPrefix(), lookUpMap);
					
					hirachicalDetailMap.put(viewPrefixDetails.getOrgid().intValue(), hPrefixMap);
				}
				else
				{
					lookUpList  = new ArrayList<LookUp>(0);
					
					lookUp 		= new LookUp();
					
					lookUp.setLookUpId(viewPrefixDetails.getCodCpdId());
					lookUp.setLookUpCode(viewPrefixDetails.getCodCpdValue());
					lookUp.setDescLangFirst(viewPrefixDetails.getCodCpdDesc());
					lookUp.setDescLangSecond(viewPrefixDetails.getCodCpdDescMar());
					lookUp.setLookUpType(viewPrefixDetails.getCpmType());
					
					if(viewPrefixDetails.getCodCpdDefault()!= null && viewPrefixDetails.getCodCpdDefault().equals(MainetConstants.IsLookUp.STATUS.YES))
					{
						lookUp.setDefaultVal(viewPrefixDetails.getCodCpdDefault());
					}
					
					if(viewPrefixDetails.getCodCpdParentId() != null)
					{
						lookUp.setLookUpParentId(viewPrefixDetails.getCodCpdParentId());
					}
					
					lookUpList.add(lookUp);
					
					lookUpMap.put(viewPrefixDetails.getComLevel(), lookUpList);
					
					hPrefixMap.put(viewPrefixDetails.getCpmPrefix(), lookUpMap);
					
					hirachicalDetailMap.put(viewPrefixDetails.getOrgid().intValue(), hPrefixMap);
				}
			}
			else
			{
				lookUpMap 	= new HashMap<Integer, List<LookUp>>(0);
				
				lookUpList  = new ArrayList<LookUp>(0);
				
				lookUp 		= new LookUp();
				
				lookUp.setLookUpId(viewPrefixDetails.getCodCpdId());
				lookUp.setLookUpCode(viewPrefixDetails.getCodCpdValue());
				lookUp.setDescLangFirst(viewPrefixDetails.getCodCpdDesc());
				lookUp.setDescLangSecond(viewPrefixDetails.getCodCpdDescMar());
				lookUp.setLookUpType(viewPrefixDetails.getCpmType());
				
				if(viewPrefixDetails.getCodCpdDefault()!= null && viewPrefixDetails.getCodCpdDefault().equals(MainetConstants.IsLookUp.STATUS.YES))
				{
					lookUp.setDefaultVal(viewPrefixDetails.getCodCpdDefault());
				}
				
				if(viewPrefixDetails.getCodCpdParentId() != null)
				{
					lookUp.setLookUpParentId(viewPrefixDetails.getCodCpdParentId());
				}
				
				lookUpList.add(lookUp);
				
				lookUpMap.put(viewPrefixDetails.getComLevel(), lookUpList);
				
				hPrefixMap.put(viewPrefixDetails.getCpmPrefix(), lookUpMap);
				
				hirachicalDetailMap.put(viewPrefixDetails.getOrgid().intValue(), hPrefixMap);
			}
		}
		else
		{
			hPrefixMap 	= new HashMap<String, Map<Integer, List<LookUp>>>(0);
			
			lookUpMap 	= new HashMap<Integer, List<LookUp>>(0);
			
			lookUpList  = new ArrayList<LookUp>(0);
			
			lookUp 		= new LookUp();
			
			lookUp.setLookUpId(viewPrefixDetails.getCodCpdId());
			lookUp.setLookUpCode(viewPrefixDetails.getCodCpdValue());
			lookUp.setDescLangFirst(viewPrefixDetails.getCodCpdDesc());
			lookUp.setDescLangSecond(viewPrefixDetails.getCodCpdDescMar());
			lookUp.setLookUpType(viewPrefixDetails.getCpmType());
			
			if(viewPrefixDetails.getCodCpdDefault()!= null && viewPrefixDetails.getCodCpdDefault().equals(MainetConstants.IsLookUp.STATUS.YES))
			{
				lookUp.setDefaultVal(viewPrefixDetails.getCodCpdDefault());
			}
			
			if(viewPrefixDetails.getCodCpdParentId() != null)
			{
				lookUp.setLookUpParentId(viewPrefixDetails.getCodCpdParentId());
			}
			
			lookUpList.add(lookUp);
			
			lookUpMap.put(viewPrefixDetails.getComLevel(), lookUpList);
			
			hPrefixMap.put(viewPrefixDetails.getCpmPrefix(), lookUpMap);
			
			hirachicalDetailMap.put(viewPrefixDetails.getOrgid().intValue(), hPrefixMap);
		}
	}

	private void loadHirachicalLevelMap(ViewPrefixDetails viewPrefixDetails,Map<Integer, Map<String, Map<Long, LookUp>>> hirachicalLevelMap) {

		LookUp levelLookUp = new LookUp();
		
		Map<Long,LookUp> levelmap = new LinkedHashMap<Long,LookUp>(0);
		
		Map<String, Map<Long,LookUp>> prefixMap = new LinkedHashMap<String, Map<Long,LookUp>>(0);
		
		if(hirachicalLevelMap.containsKey(viewPrefixDetails.getOrgid().intValue()))
		{
			prefixMap = hirachicalLevelMap.get(viewPrefixDetails.getOrgid().intValue());
			
			if(prefixMap.containsKey(viewPrefixDetails.getCpmPrefix()))
			{
				levelmap = prefixMap.get(viewPrefixDetails.getCpmPrefix());
				
				if(!levelmap.containsKey(viewPrefixDetails.getComLevel().longValue()))
				{
					levelLookUp = new LookUp();
					
					levelLookUp.setLookUpId(viewPrefixDetails.getComId());
					levelLookUp.setDescLangFirst(viewPrefixDetails.getComDesc());
					levelLookUp.setDescLangSecond(viewPrefixDetails.getComDescMar());
					levelLookUp.setLookUpCode(viewPrefixDetails.getComValue());
					levelLookUp.setLookUpType(MainetConstants.LookUp.HIERARCHICAL);
					
					levelmap.put(viewPrefixDetails.getComLevel().longValue(),levelLookUp);
					
					prefixMap.put(viewPrefixDetails.getCpmPrefix(), levelmap);
					
					hirachicalLevelMap.put(viewPrefixDetails.getOrgid().intValue(), prefixMap);
				}
			}
			else
			{
				levelmap = new LinkedHashMap<Long,LookUp>(0);
				
				levelLookUp = new LookUp();
				
				levelLookUp.setLookUpId(viewPrefixDetails.getComId());
				levelLookUp.setDescLangFirst(viewPrefixDetails.getComDesc());
				levelLookUp.setDescLangSecond(viewPrefixDetails.getComDescMar());
				levelLookUp.setLookUpCode(viewPrefixDetails.getComValue());
				levelLookUp.setLookUpType(MainetConstants.LookUp.HIERARCHICAL);
				
				levelmap.put(viewPrefixDetails.getComLevel().longValue(),levelLookUp);
				
				prefixMap.put(viewPrefixDetails.getCpmPrefix(), levelmap);
				
				hirachicalLevelMap.put(viewPrefixDetails.getOrgid().intValue(), prefixMap);
			}
		}
		else
		{
			prefixMap = new LinkedHashMap<String, Map<Long,LookUp>>(0);
			
			levelmap = new LinkedHashMap<Long,LookUp>(0);
			
			levelLookUp = new LookUp();
			
			levelLookUp.setLookUpId(viewPrefixDetails.getComId());
			levelLookUp.setDescLangFirst(viewPrefixDetails.getComDesc());
			levelLookUp.setDescLangSecond(viewPrefixDetails.getComDescMar());
			levelLookUp.setLookUpCode(viewPrefixDetails.getComValue());
			levelLookUp.setLookUpType(MainetConstants.LookUp.HIERARCHICAL);
			
			levelmap.put(viewPrefixDetails.getComLevel().longValue(),levelLookUp);
			
			prefixMap.put(viewPrefixDetails.getCpmPrefix(), levelmap);
			
			hirachicalLevelMap.put(viewPrefixDetails.getOrgid().intValue(), prefixMap);
		}
	}

	
	@Transactional(readOnly=true)
	public List<ViewPrefixDetails> getViewPrefixDetailsByType(String cpmType)
	{
		List<String> prefixList = null;
		if ("H".equalsIgnoreCase(cpmType)) {
			prefixList = Arrays.asList(Constant.HIERARCHICAL_PREFIX);
		} else {
			prefixList = Arrays.asList(Constant.NON_HIERARCHICAL_PREFIX);
		}
		
		return prefixDetailsRepository.findByCpmTypeAndCpmPrefixIn(cpmType, prefixList);
	}

	@Override
	public List<String> getNonReplicatePrefix () {
		// TODO Auto-generated method stub
		return null;
	}
	
	
}
