package com.mx.dla.dda.admin.presupuestos.bos;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.mx.dla.dda.admin.presupuestos.dtos.AmortApartadoDTO;
import com.mx.dla.dda.admin.presupuestos.dtos.ApartadoPreBD;
import com.mx.dla.dda.admin.presupuestos.dtos.PresupuestoApartadoDTO;
import com.mx.dla.dda.admin.presupuestos.dtos.PresupuestoDTO;

public class PresupuestoUtil{
	
	private static DecimalFormat df = new DecimalFormat("#.00");
	private static Logger logger =  LoggerFactory.getLogger("app");
	private static int ANIOMINIMO = 2013;
	
	public static PresupuestoApartadoDTO generarApartado(Double monto, Date fechaSap, PresupuestoApartadoDTO apartado, Long idPreApar){		
		apartado.setMontoAsignado(Double.parseDouble(df.format(monto)));
		apartado.setIdPreApart(idPreApar);
		return apartado;
	}
	
	public static Map<Integer, List<PresupuestoApartadoDTO>> getApartadosXAnio(
			List<PresupuestoApartadoDTO> apartados, List<PresupuestoDTO> presupuestos, Map<Long, Long> idTemp){		
		Map<Integer, List<PresupuestoApartadoDTO>> mapPre = new HashMap<Integer, List<PresupuestoApartadoDTO>>();
			    
		//Paso 1. Se determinan todos los aņos a configurar mayores a 2013 y las combinaciones de apartados		
	    for(int i= (Calendar.getInstance().get(Calendar.YEAR)+1); i >= ANIOMINIMO; i--)
	    {
	    	ArrayList<PresupuestoApartadoDTO> apart = new ArrayList<PresupuestoApartadoDTO>(apartados.size());
	    	apart.addAll(apartados);
	    	mapPre.put(i, apart);
	    }
	    	    	    
	    //Paso 2. Se asignan los montos de los presupuestos existentes
	    for(PresupuestoDTO pre : presupuestos)
	    {		    		
	    	if(!idTemp.containsKey(pre.getApartados().get(0).getId()))
	    		idTemp.put(pre.getApartados().get(0).getId(), pre.getApartados().get(0).getId());
	    		    	
	    	PresupuestoApartadoDTO apartado = generarApartado(pre.getMontoAsignado(), pre.getFechaSAP(), pre.getApartados().get(0), pre.getId());	    		    	
	    	
	    	if(mapPre.containsKey(pre.getAnio()))
	    	{
	    		pre.getApartados().get(0).setIdPreApart(pre.getId());
	    		pre.getApartados().get(0).setFechaSAP(pre.getFechaSAP());	    		
	    		List<PresupuestoApartadoDTO> actualizados = buscarApartado(mapPre.get(pre.getAnio()), pre.getApartados().get(0));	    		    			    			    			    		    				    			    		    		
	    		mapPre.put(pre.getAnio(), actualizados);	    			    		
	    	}	    			    	
	    	else
	    	{
	    		ArrayList<PresupuestoApartadoDTO> apart = new ArrayList<PresupuestoApartadoDTO>(apartados.size());
		    	apart.addAll(apartados);
		    	List<PresupuestoApartadoDTO> actualizados = buscarApartado(apart, apartado);   			    			    			    		    				    			    		    		
	    		mapPre.put(pre.getAnio(), actualizados);	    				    		
	    	}
	    }	    
	    return mapPre;
	}

	public static List<PresupuestoApartadoDTO> buscarApartado(List<PresupuestoApartadoDTO> apartados, PresupuestoApartadoDTO apartado){
		boolean encontrado = false;		 
		for(PresupuestoApartadoDTO apart : apartados)
		{
			if(apart.getId().longValue() == apartado.getId().longValue())
			{
				encontrado = true;				
				int index = apartados.indexOf(apart);				
				PresupuestoApartadoDTO ap = new PresupuestoApartadoDTO();
				ap.setMontoAsignado(Double.parseDouble(df.format(apartado.getMontoAsignado())));
				ap.setFechaSAP(apartado.getFechaSAP());
				ap.setId(apart.getId());
				ap.setNombre(apart.getNombre());
				ap.setType(apart.getType());
				ap.setIdPreApart(apartado.getIdPreApart());
				apartados.set(index, ap);				
			}				
		}
		if(!encontrado)
			apartados.add(apartado);
		
		return apartados;
	}
	
	public static Map<String, Double> getAmortXApartados(List<Long> idApartados, List<AmortApartadoDTO> amortizacion){											    
	    Map<String, Double> apartadosAmor = new HashMap<String, Double>();
	    for(AmortApartadoDTO am : amortizacion)
	    {
	    	if(!apartadosAmor.containsKey(am.getAnio()+"-"+am.getId()))
	    		apartadosAmor.put(am.getAnio()+"-"+am.getId(), am.getMontoAsignado());
	    	else
	    		apartadosAmor.put(am.getAnio()+"-"+am.getId(), apartadosAmor.get(am.getAnio()+"-"+am.getId()) + am.getMontoAsignado());
	    }
	    return apartadosAmor;
	}
	
	public static List<PresupuestoDTO> getSumarizadoPresupuestos(Map<String, Double> apartadosAmor,
			                          Map<Integer, List<PresupuestoApartadoDTO>> apartados, List<AmortApartadoDTO> amortizables){
		List<PresupuestoDTO> preAmortizables = new ArrayList<PresupuestoDTO>();
		
		for (Map.Entry<String, Double> amortizacion : apartadosAmor.entrySet()) 
	    {
			String[] llave = amortizacion.getKey().split("-");			
			if(apartados.get(Integer.parseInt(llave[0])) != null)
			{
				for(PresupuestoApartadoDTO apartado : apartados.get(Integer.parseInt(llave[0])))
				{
					Long idApartado = Long.parseLong(llave[1]);
					if( apartado.getId().longValue() ==  idApartado.longValue())
					{
						apartado.setMontoComprometido(amortizacion.getValue());
					}					
				}
			}												
		}		
						
		for (Map.Entry<Integer, List<PresupuestoApartadoDTO>> presupuesto : apartados.entrySet()) 
	    {
			double comprometido = 0.0;
			double asignado     = 0.0;			
			for(PresupuestoApartadoDTO apartado : presupuesto.getValue())
			{
				asignado     = apartado.getMontoAsignado()     == null ? asignado     : asignado     + apartado.getMontoAsignado().doubleValue();
				comprometido = apartado.getMontoComprometido() == null ? comprometido : comprometido + apartado.getMontoComprometido().doubleValue();
			}
			
			asignado     = Double.parseDouble(df.format(asignado));
			comprometido = Double.parseDouble(df.format(comprometido));
						                         
			PresupuestoDTO pre = new PresupuestoDTO("Amortizable", presupuesto.getKey(), asignado, comprometido, presupuesto.getValue());
			
			for(AmortApartadoDTO amort : amortizables)
			{
				if(amort.getAnio().intValue() == pre.getAnio().intValue())
					pre.setMontoAmortizable(Double.parseDouble(df.format(amort.getMontoAsignado())));
			}
						
			preAmortizables.add(pre);
	    }
				
		return preAmortizables;
	}

	
	//****
	public static PresupuestoApartadoDTO apartadoPreBD2PresupuestoApartadoDTO(ApartadoPreBD bd){
		   PresupuestoApartadoDTO pto = new PresupuestoApartadoDTO();
		   pto.setId        (bd.getIdApartado());
		   pto.setNombre    (bd.getDescApartado());
		   pto.setIdSap     (bd.getIdSap());		   		   		   
		   return pto;
	}
	/*
	public static void imprimir(Map<Integer, List<PresupuestoApartadoDTO>> mapPre){
		
		for (Map.Entry<Integer, List<PresupuestoApartadoDTO>> presupuesto : mapPre.entrySet()) 
	    {
			logger.info("llave:"+ presupuesto.getKey());
			int i=1;
			for(PresupuestoApartadoDTO apartado : presupuesto.getValue())
			{
				logger.info("ap :"+i+ ", " + apartado.toString());
				i++;
			}			
	    }
	}
	
	public static void imprimir(List<PresupuestoDTO> preAmortizables){
		
		for (PresupuestoDTO p : preAmortizables) 
	    {
			logger.info("tupe:"+ p.getType());
			logger.info("id:"+ p.getId());
			logger.info("anio:"+ p.getAnio());
			logger.info("asig:"+ p.getMontoAsignado());
			logger.info("com:"+ p.getMontoComprometido());
			logger.info("amor"+ p.getMontoAmortizable());
			logger.info("ap:"+ p.getApartados().size());
			logger.info("apart:"+p.getApartados());
	    }
	}
	*/
}
