package com.ejie.ab63.service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ejie.ab63.comun.Constantes;
import com.ejie.ab63.dao.FianzaEstablecimientoDao;
import com.ejie.ab63.model.Establecimiento;
import com.ejie.ab63.model.FianzaEstablecimiento;
import com.ejie.ab63.model.plantillas.ParametrosConfig;
import com.ejie.ab63.service.plantillas.ParametrosConfigService;
import com.ejie.x38.dto.JerarquiaDto;
import com.ejie.x38.dto.TableRequestDto;
import com.ejie.x38.dto.TableResponseDto;
import com.ejie.x38.dto.TableRowDto;

/**
 * Ab6337s00ServiceImpl  
 * 
 *  
 */

@Service(value = "fianzaEstablecimientoService")
public class FianzaEstablecimientoServiceImpl implements FianzaEstablecimientoService {

	@Autowired
	private FianzaEstablecimientoDao ab6337s00Dao;

	@Autowired
	private ReloadableResourceBundleMessageSource appMessageSource;

	@Autowired
	private EstablecimientoService establecimientoService;

	@Autowired
	private ParametrosConfigService parametrosConfigService;

	/**
	 * Inserts a single row in the Ab6337s00 table.
	 *
	 * @param ab6337s00
	 *            Ab6337s00
	 * @return Ab6337s00
	 */
	@Transactional(rollbackFor = Throwable.class)
	public FianzaEstablecimiento add(FianzaEstablecimiento ab6337s00) {
		return this.ab6337s00Dao.add(ab6337s00);
	}

	/**
	 * Updates a single row in the Ab6337s00 table.
	 *
	 * @param ab6337s00
	 *            Ab6337s00
	 * @return Ab6337s00
	 */
	@Transactional(rollbackFor = Throwable.class)
	public FianzaEstablecimiento update(FianzaEstablecimiento ab6337s00) {
		return this.ab6337s00Dao.update(ab6337s00);
	}

	/**
	 * Finds a single row in the Ab6337s00 table.
	 *
	 * @param ab6337s00
	 *            Ab6337s00
	 * @return Ab6337s00
	 */
	public FianzaEstablecimiento find(FianzaEstablecimiento ab6337s00) {
		return (FianzaEstablecimiento) this.ab6337s00Dao.find(ab6337s00);
	}

	/**
	 * Deletes a single row in the Ab6337s00 table.
	 *
	 * @param ab6337s00
	 *            Ab6337s00
	 */
	@Transactional(rollbackFor = Throwable.class)
	public void remove(FianzaEstablecimiento ab6337s00) {
		this.ab6337s00Dao.remove(ab6337s00);
	}

	/**
	 * Finds a list of rows in the Ab6337s00 table.
	 *
	 * @param ab6337s00
	 *            Ab6337s00
	 * @param tableRequestDto
	 *            TableRequestDto
	 * @return List<Ab6337s00>
	 */
	public List<FianzaEstablecimiento> findAll(FianzaEstablecimiento ab6337s00, TableRequestDto tableRequestDto) {
		return (List<FianzaEstablecimiento>) this.ab6337s00Dao.findAll(ab6337s00, tableRequestDto);
	}

	/**
	 * Finds rows in the Ab6337s00 table using like.
	 *
	 * @param ab6337s00
	 *            Ab6337s00
	 * @param tableRequestDto
	 *            TableRequestDto
	 * @param startsWith
	 *            Boolean
	 * @return List<Ab6337s00>
	 */
	public List<FianzaEstablecimiento> findAllLike(FianzaEstablecimiento ab6337s00, TableRequestDto tableRequestDto,
			Boolean startsWith) {
		return (List<FianzaEstablecimiento>) this.ab6337s00Dao.findAllLike(ab6337s00, tableRequestDto, startsWith);
	}

	/*
	 * OPERACIONES RUP_TABLE
	 */

	/**
	 * Removes rows from the Ab6337s00 table.
	 *
	 * @param filterAb6337s00
	 *            Ab6337s00
	 * @param tableRequestDto
	 *            TableRequestDto
	 * @param startsWith
	 *            Boolean
	 */
	public void removeMultiple(FianzaEstablecimiento filterAb6337s00, TableRequestDto tableRequestDto,
			Boolean startsWith) {
		this.ab6337s00Dao.removeMultiple(filterAb6337s00, tableRequestDto, startsWith);
	}

	/**
	 * Filter method in the Ab6337s00 table.
	 *
	 * @param filterAb6337s00
	 *            Ab6337s00
	 * @param tableRequestDto
	 *            TableRequestDto
	 * @param startsWith
	 *            Boolean
	 * @return TableResponseDto<Ab6337s00>
	 */
	public TableResponseDto<FianzaEstablecimiento> filter(FianzaEstablecimiento filterAb6337s00,
			TableRequestDto tableRequestDto, Boolean startsWith) {
		List<FianzaEstablecimiento> listaAb6337s00 = this.ab6337s00Dao.findAllLike(filterAb6337s00, tableRequestDto,
				false);

		for (FianzaEstablecimiento fianza : listaAb6337s00) {

			if (fianza.getIdTipoFianza() != null) {

				if ("I".equals(fianza.getIdTipoFianza())) {

					fianza.setDescTipoFianza(
							appMessageSource.getMessage("fianza.individual", null, LocaleContextHolder.getLocale()));

				} else if (("C").equals(fianza.getIdTipoFianza())) {

					fianza.setDescTipoFianza(
							appMessageSource.getMessage("fianza.colectiva", null, LocaleContextHolder.getLocale()));

				}

			}

		}

		Long recordNum = this.ab6337s00Dao
				.findAllLikeCount(filterAb6337s00 != null ? filterAb6337s00 : new FianzaEstablecimiento(), false);
		if (tableRequestDto.getMultiselection().getSelectedIds() != null) {
			List<TableRowDto<FianzaEstablecimiento>> reorderSelection = this.ab6337s00Dao
					.reorderSelection(filterAb6337s00, tableRequestDto, startsWith);
			return new TableResponseDto<FianzaEstablecimiento>(tableRequestDto, recordNum, listaAb6337s00,
					reorderSelection);
		}
		return new TableResponseDto<FianzaEstablecimiento>(tableRequestDto, recordNum, listaAb6337s00);
	}

	/**
	 * Searches rows in the Ab6337s00 table.
	 *
	 * @param filterAb6337s00
	 *            Ab6337s00
	 * @param searchAb6337s00
	 *            Ab6337s00
	 * @param tableRequestDto
	 *            TableRequestDto
	 * @param startsWith
	 *            Boolean
	 * @return List<TableRowDto<Ab6337s00>>
	 */
	public List<TableRowDto<FianzaEstablecimiento>> search(FianzaEstablecimiento filterAb6337s00,
			FianzaEstablecimiento searchAb6337s00, TableRequestDto tableRequestDto, Boolean startsWith) {
		return this.ab6337s00Dao.search(filterAb6337s00, searchAb6337s00, tableRequestDto, startsWith);
	}

	/**
	 * Reorder the selection made in Ab6337s00 table.
	 *
	 * @param filterAb6337s00
	 *            Ab6337s00
	 * @param tableRequestDto
	 *            TableRequestDto
	 * @param startsWith
	 *            Boolean
	 * @return Object
	 */
	public Object reorderSelection(FianzaEstablecimiento filterAb6337s00, TableRequestDto tableRequestDto,
			Boolean startsWith) {
		return this.ab6337s00Dao.reorderSelection(filterAb6337s00, tableRequestDto, startsWith);
	}

	/*
	 * OPERACIONES RUP_TABLE JERARQUIA
	 */

	/**
	 * Finder method in the hierarchical the Ab6337s00 table.
	 *
	 * @param filterAb6337s00
	 *            Ab6337s00
	 * @param tableRequestDto
	 *            TableRequestDto
	 * @param startsWith
	 *            Boolean
	 * @return TableResponseDto<JerarquiaDto<Ab6337s00>>
	 */
	public TableResponseDto<JerarquiaDto<FianzaEstablecimiento>> jerarquia(FianzaEstablecimiento filterAb6337s00,
			TableRequestDto tableRequestDto, Boolean startsWith) {
		List<JerarquiaDto<FianzaEstablecimiento>> listaAb6337s00 = this.ab6337s00Dao
				.findAllLikeJerarquia(filterAb6337s00, tableRequestDto);
		Long recordNum = this.ab6337s00Dao.findAllLikeCountJerarquia(filterAb6337s00, tableRequestDto);
		return new TableResponseDto<JerarquiaDto<FianzaEstablecimiento>>(tableRequestDto, recordNum, listaAb6337s00);
	}

	/**
	 * Finder method for siblings rows in the hierarchical the Ab6337s00 table.
	 *
	 * @param filterAb6337s00
	 *            Ab6337s00
	 * @param tableRequestDto
	 *            TableRequestDto
	 * @return TableResponseDto<JerarquiaDto<Ab6337s00>>
	 */
	public TableResponseDto<JerarquiaDto<FianzaEstablecimiento>> jerarquiaChildren(
			FianzaEstablecimiento filterAb6337s00, TableRequestDto tableRequestDto) {
		TableResponseDto<JerarquiaDto<FianzaEstablecimiento>> tableResponseDto = new TableResponseDto<JerarquiaDto<FianzaEstablecimiento>>();
		tableResponseDto.addAdditionalParam(TableResponseDto.CHILDREN,
				this.ab6337s00Dao.findAllChild(filterAb6337s00, tableRequestDto));
		return tableResponseDto;
	}

	@Override
	public List<BigDecimal> calcularFianzas(FianzaEstablecimiento fianza, String idGrupo, int flag) {

		List<BigDecimal> listaValores = new ArrayList<BigDecimal>();

		BigDecimal totalFianzasCalculadas = new BigDecimal(0);
		BigDecimal totalFianzasDefinidas = new BigDecimal(0);

		BigDecimal baremo = obtenerBaremo(fianza, idGrupo);

		if (null != baremo) {
			totalFianzasCalculadas = totalFianzasCalculadas.add(baremo);
			Establecimiento establecimiento = new Establecimiento();
			establecimiento.setFranquicia(fianza.getFranquicia());

			Long numEstabRelacionados = establecimientoService.findEstablecimientoByOfiPpalCount(establecimiento, false,
					true);

			if (numEstabRelacionados - 6 > 0) {
				BigDecimal excesoEst = new BigDecimal(numEstabRelacionados - 6.0D);

				BigDecimal fianzaAdicional = obtenerFianzaAdicional(fianza, idGrupo);
				totalFianzasCalculadas = totalFianzasCalculadas.add(fianzaAdicional.multiply(excesoEst));

			}
		} else {
			totalFianzasCalculadas = null;
		}

		List<FianzaEstablecimiento> fianzas = this.ab6337s00Dao.getFianzasByEstablecimiento(fianza);

		for (FianzaEstablecimiento f : fianzas) {
			if (f.getNumImporteFianza() != null) {
				totalFianzasDefinidas = totalFianzasDefinidas.add(f.getNumImporteFianza());
			}
		}

		listaValores.add(totalFianzasDefinidas);
		if (flag == 1) {
			listaValores.add(totalFianzasCalculadas);
		}

		return listaValores;

	}

	@Override
	public BigDecimal obtenerBaremo(FianzaEstablecimiento fianza, String idGrupo) {

		BigDecimal baremo = null;

		if (!"".equals(idGrupo)) {
			ParametrosConfig parametrosConfigFind = new ParametrosConfig();
			parametrosConfigFind.setDescripcion(Constantes.BAREMO + idGrupo);
			ParametrosConfig parametrosConfig = parametrosConfigService.find(parametrosConfigFind);
			if (null != parametrosConfig) {
				baremo = new BigDecimal(parametrosConfig.getValor());
			}
		}

		if (null != baremo) {
			baremo = reduccionFianzaColectiva(fianza, baremo);
		}

		return baremo;
	}

	@Override
	public BigDecimal obtenerFianzaAdicional(FianzaEstablecimiento fianza, String idGrupo) {

		ParametrosConfig parametrosConfigFind = new ParametrosConfig();
		parametrosConfigFind.setDescripcion(Constantes.FIANZA_ADICIONAL);
		ParametrosConfig parametrosConfig = parametrosConfigService.find(parametrosConfigFind);
		BigDecimal fianzaAdicional = null;
		if (null != parametrosConfig) {
			fianzaAdicional = new BigDecimal(parametrosConfig.getValor());
			fianzaAdicional = reduccionFianzaColectiva(fianza, fianzaAdicional);
		}
		return fianzaAdicional;
	}

	@Override
	public BigDecimal reduccionFianzaColectiva(FianzaEstablecimiento fianza, BigDecimal baremo) {

		BigDecimal importeReducido = new BigDecimal(0.0D);
		BigDecimal cero = new BigDecimal(0.0D);

		List<FianzaEstablecimiento> fianzas = this.ab6337s00Dao.getFianzasByEstablecimiento(fianza);

		if (null != fianza && fianzas.size() == 0) {
			return baremo;
		}

		for (FianzaEstablecimiento f : fianzas) {

			if (f.getNumImporteFianza().compareTo(cero) == 1 && StringUtils.isNotBlank(f.getIdTipoFianza())) {

				if ("C".equals(f.getIdTipoFianza())) {

					BigDecimal divisor = new BigDecimal(2.0D);
					importeReducido = baremo.divide(divisor, 2, 4);

					break;

				} else {

					importeReducido = baremo;
				}
			}
		}

		return importeReducido;
	}

}
