package it.micegroup.gestioneferie.pianificazioneferie.service;

import java.util.Map;
import java.util.List;
import java.util.Locale;
import java.util.HashMap;
import java.util.Optional;
import java.util.ArrayList;
import java.util.Collection;
import java.util.ResourceBundle;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;

import org.springframework.context.i18n.LocaleContextHolder;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import net.sf.jasperreports.engine.JRParameter;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;

import it.micegroup.voila2runtime.filter.LongFilter;

import it.micegroup.gestioneferie.pianificazioneferie.entity.DammtiPianiFerie;

import it.micegroup.gestioneferie.pianificazioneferie.entity.DammtiPianiFerieKey;

import it.micegroup.gestioneferie.pianificazioneferie.entity.DmotivazioniAlertPf;
import it.micegroup.gestioneferie.pianificazioneferie.entity.DpianiFerie;
import it.micegroup.gestioneferie.pianificazioneferie.entity.DmotivazioniAlertPfKey;

import it.micegroup.gestioneferie.pianificazioneferie.entity.DammtiPianiFerie_;
import it.micegroup.gestioneferie.pianificazioneferie.criteria.DammtiPianiFerieCriteria;
import it.micegroup.gestioneferie.pianificazioneferie.repository.DammtiPianiFerieRepository;
import it.micegroup.voila2runtime.specification.FilterService;

import it.micegroup.gestioneferie.pianificazioneferie.entity.DammtiPianiFerie_;
import it.micegroup.gestioneferie.pianificazioneferie.entity.DammtiPianiFerieKey_;
import it.micegroup.gestioneferie.pianificazioneferie.entity.DmotivazioniAlertPf_;
import it.micegroup.gestioneferie.pianificazioneferie.entity.DmotivazioniAlertPfKey_;

import it.micegroup.gestioneferie.pianificazioneferie.entity.DpianiFerie_;
import it.micegroup.gestioneferie.pianificazioneferie.entity.DstatiPianoFerie_;
import it.micegroup.gestioneferie.pianificazioneferie.entity.DstatiPianoFerieKey_;

import org.springframework.data.domain.PageImpl;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import it.micegroup.gestioneferie.libs.service.BaseServiceImpl;
import it.micegroup.gestioneferie.pianificazioneferie.entity.DammtiPianiFerieKey_;

import it.micegroup.voila2runtime.exception.BusinessException;
import net.sf.jasperreports.engine.JRException;

@RequiredArgsConstructor
@Service
@Transactional
public class DammtiPianiFerieServiceImpl extends BaseServiceImpl implements DammtiPianiFerieService {

	private final DammtiPianiFerieRepository dammtiPianiFerieRepository;
	private final FilterService<DammtiPianiFerie> filterService;

	// CHILD SERVICES

	@SuppressWarnings("unused")
	private static final Logger LOGGER = LogManager.getLogger(DammtiPianiFerieServiceImpl.class);

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * it.micegroup.gestioneferie.pianificazioneferie.service.GenericEntityService#
	 * findAll(org. springframework.data.domain.Pageable)
	 */
	@Override
	@Transactional(readOnly = true)
	public Page<DammtiPianiFerie> findAll(Pageable pageable) {
		return dammtiPianiFerieRepository.findAll(pageable);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * it.micegroup.gestioneferie.pianificazioneferie.service.GenericEntityService#
	 * findAll()
	 */
	@Override
	@Transactional(readOnly = true)
	public List<DammtiPianiFerie> findAll() {
		return dammtiPianiFerieRepository.findAll();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * it.micegroup.gestioneferie.pianificazioneferie.service.GenericEntityService#
	 * findByCriteria(java. lang.Object, org.springframework.data.domain.Pageable)
	 */
	@Override
	@Transactional(readOnly = true)
	public Page<DammtiPianiFerie> findByCriteria(DammtiPianiFerieCriteria criteria, Pageable pageable) {
		final Specification<DammtiPianiFerie> specification = createSpecification(criteria);
		return dammtiPianiFerieRepository.findAll(specification, pageable);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * it.micegroup.gestioneferie.pianificazioneferie.service.GenericEntityService#
	 * findByCriteria(java. lang.Object)
	 */
	@Override
	@Transactional(readOnly = true)
	public List<DammtiPianiFerie> findByCriteria(DammtiPianiFerieCriteria criteria) {
		final Specification<DammtiPianiFerie> specification = createSpecification(criteria);
		return dammtiPianiFerieRepository.findAll(specification);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * it.micegroup.gestioneferie.pianificazioneferie.service.GenericEntityService#
	 * findById(java.lang. Object)
	 */
	@Override
	@Transactional(readOnly = true)
	public Optional<DammtiPianiFerie> findById(DammtiPianiFerieKey id) {
		return dammtiPianiFerieRepository.findByDammtiPianiFerieKey(id);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * it.micegroup.gestioneferie.pianificazioneferie.service.GenericEntityService#
	 * exists(java.lang. Object)
	 */
	@Override
	public boolean exists(DammtiPianiFerieKey id) {
		return dammtiPianiFerieRepository.existsById(id);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * it.micegroup.gestioneferie.pianificazioneferie.service.GenericEntityService#
	 * insert(java. lang.Object)
	 */
	@Override
	public DammtiPianiFerie insert(@Valid DammtiPianiFerie entity) {
		return dammtiPianiFerieRepository.save(entity);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * it.micegroup.gestioneferie.pianificazioneferie.service.GenericEntityService#
	 * update(java. lang.Object)
	 */
	@Override
	public DammtiPianiFerie update(@Valid DammtiPianiFerie entity) {
		return dammtiPianiFerieRepository.save(entity);
	}

	@Override
	public void delete(DammtiPianiFerie entity) {
		dammtiPianiFerieRepository.delete(entity);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * it.micegroup.gestioneferie.pianificazioneferie.service.GenericEntityService#
	 * deleteById(java.lang. Object)
	 */
	@Override
	public void deleteById(DammtiPianiFerieKey id) {
		dammtiPianiFerieRepository.deleteById(id);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * it.micegroup.gestioneferie.pianificazioneferie.service.GenericEntityService#
	 * deleteByIdIn(java.lang. Object)
	 */
	@Override
	public void deleteByIdIn(Collection<DammtiPianiFerieKey> ids) {
		dammtiPianiFerieRepository.deleteByIdIn(ids);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * it.micegroup.gestioneferie.pianificazioneferie.service.GenericEntityService#
	 * findByObjectKey(java.lang.String)
	 */
	@Override
	@Transactional(readOnly = true)
	public Optional<DammtiPianiFerie> findByObjectKey(String id) {
		DammtiPianiFerie dammtiPianiFerie = new DammtiPianiFerie(id);

		return findById(dammtiPianiFerie.getDammtiPianiFerieKey());
	}

	@Override
	public Page<DammtiPianiFerie> findByTheDmotivazioniAlertPf(DmotivazioniAlertPf parentEntity, Pageable pageable) {
		return dammtiPianiFerieRepository.findByTheDmotivazioniAlertPf(parentEntity, pageable);
	}

	@Override
	public Page<DammtiPianiFerie> findByTheDpianiFerie(DpianiFerie parentEntity, Pageable pageable) {
		return dammtiPianiFerieRepository.findByTheDpianiFerie(parentEntity, pageable);
	}

	/**
	 * Convert DammtiPianiFerieCriteria to a {@link Specification}
	 * 
	 * @param criteria
	 * @return
	 */
	private Specification<DammtiPianiFerie> createSpecification(DammtiPianiFerieCriteria criteria) {
		Specification<DammtiPianiFerie> specification = Specification.where(null);

		if (criteria != null) {
			// Attribute filters
			if (criteria.getSequIdAmmtoPianiFerie() != null) {
				specification = specification.and(filterService.generateRangeSpecification(
						criteria.getSequIdAmmtoPianiFerie(), DammtiPianiFerie_.sequIdAmmtoPianiFerie));
			}
			if (criteria.getDescMotivazioneRigetto() != null) {
				specification = specification.and(filterService.generateStringSpecification(
						criteria.getDescMotivazioneRigetto(), DammtiPianiFerie_.descMotivazioneRigetto));
			}
			if (criteria.getStatAdesione() != null) {
				specification = specification.and(filterService.generateStringSpecification(criteria.getStatAdesione(),
						DammtiPianiFerie_.statAdesione));
			}
			if (criteria.getFkAmministrato() != null) {
				specification = specification.and(filterService.generateRangeSpecification(criteria.getFkAmministrato(),
						DammtiPianiFerie_.fkAmministrato));
			}
			if (criteria.getFkMotivazioneAlertPf() != null) {
				specification = specification.and(filterService.generateRangeSpecification(
						criteria.getFkMotivazioneAlertPf(), DammtiPianiFerie_.fkMotivazioneAlertPf));
			}
			if (criteria.getFkPianoFerie() != null) {
				specification = specification.and(filterService.generateRangeSpecification(criteria.getFkPianoFerie(),
						DammtiPianiFerie_.fkPianoFerie));
			}
			if (criteria.getUtenteUltimaModifica() != null) {
				specification = specification.and(filterService.generateStringSpecification(
						criteria.getUtenteUltimaModifica(), DammtiPianiFerie_.utenteUltimaModifica));
			}
			if (criteria.getDataFineRecord() != null) {
				specification = specification.and(filterService.generateRangeSpecification(criteria.getDataFineRecord(),
						DammtiPianiFerie_.dataFineRecord));
			}
			if (criteria.getDataUltimaModifica() != null) {
				specification = specification.and(filterService.generateRangeSpecification(
						criteria.getDataUltimaModifica(), DammtiPianiFerie_.dataUltimaModifica));
			}
			if (criteria.getFlagEliminato() != null) {
				specification = specification.and(filterService.generateStringSpecification(criteria.getFlagEliminato(),
						DammtiPianiFerie_.flagEliminato));
			}
			if (criteria.getDataInizioRecord() != null) {
				specification = specification.and(filterService.generateRangeSpecification(
						criteria.getDataInizioRecord(), DammtiPianiFerie_.dataInizioRecord));
			}

			// CompositeKey Filters

			if (criteria.getTheDmotivazioniAlertPfObjectKey() != null) {
				DmotivazioniAlertPf dmotivazioniAlertPf = new DmotivazioniAlertPf(
						criteria.getTheDmotivazioniAlertPfObjectKey());

			}
			if (criteria.getTheDpianiFerieObjectKey() != null) {
				DpianiFerie dpianiFerie = new DpianiFerie(criteria.getTheDpianiFerieObjectKey());

				specification = specification
						.and(filterService.generateEqualsSpecification(dpianiFerie.getSequIdPianoFerie(),
								r -> r.get(DammtiPianiFerie_.theDpianiFerie).get(DpianiFerie_.sequIdPianoFerie)));
			}

		}
		return specification;
	}

	/*
	 * 
	 * @see it.micegroup.gestioneferie.pianificazioneferie.service.
	 * DammtiPianiFerieService#findDmotivazioniAlertPfBytheDpianiFerie(it.micegroup.
	 * gestioneferie.pianificazioneferie.entity.DpianiFerie,
	 * org.springframework.data.domain.Pageable)
	 */
	@Override
	@Transactional(readOnly = true)
	public Page<DmotivazioniAlertPf> findDmotivazioniAlertPfByTheDpianiFerie(DpianiFerie dpianiFerie,
			Pageable pageable) {
		Page<DammtiPianiFerie> dammtiPianiFeriePage = dammtiPianiFerieRepository.findByTheDpianiFerie(dpianiFerie,
				pageable);
		List<DmotivazioniAlertPf> content = dammtiPianiFeriePage.getContent().stream()
				.map(DammtiPianiFerie::getTheDmotivazioniAlertPf).collect(Collectors.toList());
		Page<DmotivazioniAlertPf> result = new PageImpl<DmotivazioniAlertPf>(content, pageable,
				dammtiPianiFeriePage.getTotalElements());
		return result;
	}

	/*
	 * 
	 * @see it.micegroup.gestioneferie.pianificazioneferie.service.
	 * DammtiPianiFerieService#findDpianiFerieBytheDmotivazioniAlertPf(it.micegroup.
	 * gestioneferie.pianificazioneferie.entity.DmotivazioniAlertPf,
	 * org.springframework.data.domain.Pageable)
	 */
	@Override
	@Transactional(readOnly = true)
	public Page<DpianiFerie> findDpianiFerieByTheDmotivazioniAlertPf(DmotivazioniAlertPf dmotivazioniAlertPf,
			Pageable pageable) {
		Page<DammtiPianiFerie> dammtiPianiFeriePage = dammtiPianiFerieRepository
				.findByTheDmotivazioniAlertPf(dmotivazioniAlertPf, pageable);
		List<DpianiFerie> content = dammtiPianiFeriePage.getContent().stream().map(DammtiPianiFerie::getTheDpianiFerie)
				.collect(Collectors.toList());
		Page<DpianiFerie> result = new PageImpl<DpianiFerie>(content, pageable,
				dammtiPianiFeriePage.getTotalElements());
		return result;
	}

	@Override
	@Transactional()
	public DammtiPianiFerie bulkUpdate(DammtiPianiFerie dammtiPianiFerie) {

		DammtiPianiFerie update = this.update(dammtiPianiFerie);

		return update;
	}
}
