package com.mx.dla.dda.contrato.license.terminos.bos;

import java.math.RoundingMode;
import java.net.URLDecoder;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.ibatis.exceptions.PersistenceException;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.mx.dla.dda.contrato.license.exceptions.dtos.LicenseException;
import com.mx.dla.dda.contrato.license.terminos.daos.TerminosFeeDAO;
import com.mx.dla.dda.contrato.materiales.daos.MaterialesDAO;
import com.mx.dla.dda.contrato.terminos.dtos.ContratoConsultaDTO;
import com.mx.dla.dda.contrato.terminos.dtos.PagoTerminoDTO;
import com.mx.dla.dda.contrato.terminos.dtos.TerminoBD;
import com.mx.dla.dda.contrato.terminos.dtos.TerminoDTO;
import com.mx.dla.global.bos.BaseBO;

@Service
public class TerminosFeeBO extends BaseBO{
		
	@Autowired
	private TerminosFeeDAO terminosDAO;
	
	@Autowired
	private MaterialesDAO materialesDAO;		
		
	public TerminoDTO getTerminos(Long idContrato) throws LicenseException{
		TerminoDTO termino = new TerminoDTO();
		
		try
		{
			TerminoBD term = terminosDAO.getTermino(idContrato);						
			
			if(term == null)
				termino.setVacio(true);
			else
			{
				if(term.getAnticipoMonto() != null)
				{
					PagoTerminoDTO pago = new PagoTerminoDTO(Double.parseDouble(term.getAnticipoMonto()), term.getAnticipoComentario(), getFecha(term.getAnticipoFecha()));
					termino.setPagoAnticipado(pago);				
				}
										
				if(term.getTipoPago() != null && term.getTipoPago().compareTo("MENSUAL") == 0)
				{
					termino.setPagoMensual(true);				
				}
				   		
				if(term.getTipoPago() != null && term.getTipoPago().compareTo("PREDEFINIDO") == 0 && 
				   term.getTipoPredefinido().compareTo("EXHIBICION") == 0)
				{
					termino.setPagoInicioExhibicion(true);				
				}
							
				if(term.getTipoPago() != null && term.getTipoPago().compareTo("PREDEFINIDO") == 0 && 
				   term.getTipoPredefinido().compareTo("PERIODICO") == 0)
				{
					List<TerminoBD> periodicos = terminosDAO.getTerminoPeriodicos(idContrato);
					List<PagoTerminoDTO> pagoPeriodicos = new ArrayList<PagoTerminoDTO>();
					
					for(TerminoBD pago : periodicos)
					{
						PagoTerminoDTO pagoT = new PagoTerminoDTO(Double.parseDouble(pago.getMonto()), pago.getComentario(), getFecha(pago.getFecha()));
						pagoPeriodicos.add(pagoT);
					}
					termino.setPagoPeriodicos(pagoPeriodicos);				
				}			
				termino.setComentario(term.getComentarioGeneral());
				
				int numero = term.getTotalTitulos() == null ? 0 : Integer.parseInt(term.getTotalTitulos());
				termino.setNumeroTitulos(numero);  //verificar de donde obtenerlo
				
				double costo = term.getCosto() == null ? 0 : Double.parseDouble(term.getCosto());
				termino.setCostoContrato(costo);
			}
												
			return termino;
				
		}catch(PersistenceException  ibe){
			  throw new LicenseException("Ocurrió un error al obtener los datos.", ibe);			   			   			   
		}catch(Exception e){
			  throw new LicenseException("Ocurrió un error al obtener los datos.", e);			   
		}
	}
		
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public void guardarTerminos(String json, Long idContrato) throws LicenseException{		
		try		
		{
			logger.debug(json);
			//Veerificar donde guardar costo contrato y numero de titulos
			ObjectMapper mapper = new ObjectMapper();													
			TerminoDTO termino = mapper.readValue(json, TerminoDTO.class);
			
			TerminoBD terminobd = new TerminoBD();
			terminobd.setIdContrato(idContrato);
			
			this.eliminarTerminos(idContrato);
			
			if(termino.getPagoAnticipado() != null)
			{			
				terminobd.setAnticipoComentario(URLDecoder.decode(termino.getPagoAnticipado().getDescripcion(), "UTF-8"));
				terminobd.setAnticipoFecha(crearFecha(termino.getPagoAnticipado().getFecha()));
				terminobd.setAnticipoMonto(String.valueOf(termino.getPagoAnticipado().getMonto()));						
			}
									
			if(termino.getPagoMensual() != null && termino.getPagoMensual())
			{
				terminobd.setTipoPago("MENSUAL");					
			}
			   		
			if(termino.getPagoInicioExhibicion() != null && termino.getPagoInicioExhibicion())
			{
				terminobd.setTipoPago("PREDEFINIDO");			
				terminobd.setTipoPredefinido("EXHIBICION");								
			}
						
			if(termino.getPagoPeriodicos() != null)
			{
				terminobd.setTipoPago("PREDEFINIDO");
				terminobd.setTipoPredefinido("PERIODICO");									
			}
			
			terminobd.setComentarioGeneral(URLDecoder.decode(termino.getComentario(), "UTF-8"));
			String numTitulos = termino.getNumeroTitulos() == null ? null : String.valueOf(termino.getNumeroTitulos());
			String costo      = termino.getCostoContrato() == null ? null : String.valueOf(termino.getCostoContrato());			
			
			
			terminobd.setTotalTitulos(numTitulos);
			terminobd.setCosto(costo);
			terminosDAO.guardarTermino(terminobd);		
			
			if(termino.getPagoPeriodicos() != null)
			{			
				List<TerminoBD> pagoPeriodicos = new ArrayList<TerminoBD>();			
				for(PagoTerminoDTO pago : termino.getPagoPeriodicos())
				{
					TerminoBD pagoT = new TerminoBD();				
					pagoT.setMonto(String.valueOf(pago.getMonto()));				
					pagoT.setFecha(crearFecha(pago.getFecha()));
					pagoT.setComentario(URLDecoder.decode(pago.getDescripcion(), "UTF-8"));
					pagoT.setIdContrato(idContrato);
					pagoPeriodicos.add(pagoT);
				}						
				terminosDAO.guardarTerminoPago(pagoPeriodicos);
			}						
		
			this.actualizarCostoTitulos(idContrato, termino.getCostoContrato(), termino.getNumeroTitulos());
			
		}catch(PersistenceException  ibe){			   
			   throw new LicenseException("Ocurrió un error al guardar los datos.", ibe);			   
		}catch(Exception e){
			   throw new LicenseException("Ocurrió un error al guardar los datos.", e);		   
		}
	}
		
	private void eliminarTerminos(Long idContrato){
		terminosDAO.eliminarTerminoPago(idContrato);
		terminosDAO.eliminarTermino(idContrato);		
	}
	
	public ContratoConsultaDTO getInformacionContrato(Long idContrato, TerminoDTO termino){
		//Tipo contrato, fecha inicio, costo contrato, costo materiales,		
		
		Double materialesCosto       = materialesDAO.buscarCostoTotalMateriales(idContrato);
		ContratoConsultaDTO contrato = terminosDAO.consultaContrato(new ContratoConsultaDTO(idContrato));				
		termino.setCostoMateriales(materialesCosto);		
		return contrato;
	}	

	public void actualizarCostoTitulos(Long idContrato, Double costoContrato, Integer numTitulos){
		
		DecimalFormat df = new DecimalFormat("#.##########");		
		df.setRoundingMode(RoundingMode.CEILING);
		
		Double valor  = costoContrato / numTitulos;		
		String valorS = df.format(valor);
		
		terminosDAO.actualizarCostoTitulos(idContrato, valorS);		
	}
	
	private Date crearFecha(String valor) throws ParseException{	
		DateFormat formatter1 = new SimpleDateFormat("MM/dd/yyyy");
		Date fecha = formatter1.parse(valor);
        return fecha;
	}
	
	private String getFecha(Date fecha){		
		SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");		
		return sdf.format(fecha);
	}
}