package es.dalocar.software.services;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.log4j.Logger;
import org.hibernate.ObjectNotFoundException;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;

import es.dalocar.software.ApplicationManager;
import es.dalocar.software.beans.Amortizacion;
import es.dalocar.software.beans.AmortizacionId;
import es.dalocar.software.beans.Factura;
import es.dalocar.software.beans.FacturaId;
import es.dalocar.software.beans.FacturaSearch;
import es.dalocar.software.beans.LineaAmortizacion;
import es.dalocar.software.daos.AmortizacionDAO;
import es.dalocar.software.daos.ClienteDAO;
import es.dalocar.software.daos.LineaAmortizacionDAO;

public class AmortizacionService {
	
	private static final Logger log = Logger.getLogger(AmortizacionService.class);
	
	private AmortizacionDAO amortizacionDAO;
	private LineaAmortizacionDAO lineaAmortizacionDAO;
	private ClienteDAO clienteDAO;
	
	private ApplicationManager manager;
	
	
	/**
	 * @param manager
	 */
	public AmortizacionService(ApplicationManager manager)
	{
		this.manager  = manager;
		this.amortizacionDAO = manager.getAmortizacionDAO();
		this.lineaAmortizacionDAO = manager.getLineaAmortizacionDAO();	
		this.clienteDAO = manager.getClienteDAO();
	}
	

	/**
	 * Devuelve una Factura rellena con sus diferentes líneas
	 * @param id {@link FacturaId} Identificador de la factura
	 * @return Factura Rellena con sus lineas
	 * @throws ObjectNotFoundException
	 */
	public Amortizacion getAmortizacionById(AmortizacionId id) throws ObjectNotFoundException{
		
		Amortizacion factura = this.amortizacionDAO.findById(id);
		
		if(factura == null)
			throw new ObjectNotFoundException(id, Factura.class.toString());
		
		factura.getLineaamortizacions().addAll(this.lineaAmortizacionDAO.findByAmortizacion(factura));		
		
		return factura;
	}
	
	/**
	 * Devuelve todas las facturas de la base de datos.
	 * @return List
	 */
	public List findAll() {		
		return this.amortizacionDAO.findAll();
	}
	
	/**
	 * Guarda los cambios 
	 * @param factura
	 */
	public void saveAmortizacion(Amortizacion factura) {		
		this.amortizacionDAO.saveOrUpdate(factura);
		this.lineaAmortizacionDAO.saveLineasFactura(factura);	
	}
	
	/**
	 * Realiza una búsqueda de los objetos similares al parámetro search
	 * @param search
	 */
	public List search(FacturaSearch search) {
		
		DetachedCriteria criteria = DetachedCriteria.forClass(Factura.class);
		if (!search.getNumero().equals(""))
			criteria.add(Restrictions.like("id.numero", Integer.valueOf(search.getNumero())));
		if (!search.getAnyo().equals(""))
			criteria.add(Restrictions.eq("id.anyo",  Integer.valueOf(search.getAnyo())));		
		if (!search.getNumCliente().equals(""))
			criteria.add(Restrictions.eq("cliente.identificador",  Integer.valueOf(search.getNumCliente())));

		return this.amortizacionDAO.getHibernateTemplate().findByCriteria(criteria);
	}
	
	/**
	 * Devuelve el siguiente numero de factura a crear para el año pasado por parámetro
	 * @param year
	 * @return
	 */
	public Integer getNextIdAmortizacion(int year) {
		List lista = this.amortizacionDAO.getHibernateTemplate().find("select max(id.numero) from Amortizacion where id.anyo=" + year);
		Integer siguiente = (Integer)lista.get(0);
		if(siguiente == null)
			siguiente = new Integer(0);
		if(log.isDebugEnabled())
			log.debug("Siguiente factura: " + siguiente);
		
		return new Integer(siguiente.intValue() + 1);		
	}
	
	/**
	 * Devuelve una Amortizacion rellena con sus diferentes líneas
	 * @param id {@link FacturaId} Identificador de la factura
	 * @return Factura Rellena con sus lineas
	 * @throws ObjectNotFoundException
	 * @throws InvocationTargetException 
	 * @throws IllegalAccessException 
	 */
	public Amortizacion copyAmortizacionById(AmortizacionId id) {
		
		Amortizacion factura = this.amortizacionDAO.findById(id);
		
		if(factura == null)
			throw new ObjectNotFoundException(id, Amortizacion.class.toString());
		
		factura.getLineaamortizacions().addAll(this.lineaAmortizacionDAO.findByAmortizacion(factura));	
		Amortizacion nuevaFactura = new Amortizacion();
		
		try {
			BeanUtils.copyProperties(nuevaFactura, factura);
		
		Calendar calendar = Calendar.getInstance();
		//Nuevo identificador
		nuevaFactura.getId().setNumero(getNextIdAmortizacion(calendar.get(Calendar.YEAR)));
		nuevaFactura.getId().setAnyo(Integer.valueOf(calendar.get(Calendar.YEAR)));
		//Copiamos las lineas
		Iterator it = factura.getLineaamortizacions().iterator();
		nuevaFactura.setLineaamortizacions(new ArrayList());
		while(it.hasNext()) {
			LineaAmortizacion lineaNueva = new LineaAmortizacion();
			LineaAmortizacion linea = (LineaAmortizacion)it.next();
			BeanUtils.copyProperties(lineaNueva, linea);
			lineaNueva.getId().setAnyofactura(nuevaFactura.getId().getAnyo());
			lineaNueva.getId().setNumerofactura(nuevaFactura.getId().getNumero());
			lineaNueva.setAmortizacion(nuevaFactura);
			nuevaFactura.getLineaamortizacions().add(lineaNueva);			
		}
		amortizacionDAO.saveOrUpdate(nuevaFactura);
		lineaAmortizacionDAO.saveLineasFactura(nuevaFactura);
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
		return nuevaFactura;
	}
	
	//Borra las facturas contenidas en una lista de facturas	
	public boolean deleteListaFacturas(List list) {
		Iterator it = list.iterator();
		while(it.hasNext()) {
			Amortizacion f =(Amortizacion) it.next();		
			//Borramos las lineas
			lineaAmortizacionDAO.deleteFromAmortizacion(f);
			//Borramos la factura
			amortizacionDAO.delete(f);			
		}
		
		
		return true;
	}
	
	
	
	
}
