package com.ejie.ab63.service;

import java.util.Date;
import java.util.List;

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.AlojamientoDao;
import com.ejie.ab63.model.Alojamiento;
import com.ejie.ab63.model.AseoAlojamiento;
import com.ejie.ab63.model.EstablecimientoData;
import com.ejie.ab63.model.HabitacionAlojamiento;
import com.ejie.ab63.model.TipoAseo;
import com.ejie.ab63.model.TipoHabitacion;
import com.ejie.x38.dto.JerarquiaDto;
import com.ejie.x38.dto.TableRequestDto;
import com.ejie.x38.dto.TableResponseDto;
import com.ejie.x38.dto.TableRowDto;

/**
 * Ab6323s00ServiceImpl  
 * 
 *  
 */

@Service(value = "alojamientoService")
public class AlojamientoServiceImpl implements AlojamientoService {

	@Autowired
	private ReloadableResourceBundleMessageSource appMessageSource;

	@Autowired
	private AlojamientoDao alojamientoDao;

	@Autowired
	private HabitacionAlojamientoService habitacionAlojamientoService;

	@Autowired
	private AseoAlojamientoService aseoAlojamientoService;

	@Autowired
	private EstablecimientoDataService establecimientoDataService;

	@Autowired
	TipoAseoService tipoAseoService;

	@Autowired
	TipoHabitacionService tipoHabitacionService;

	/**
	 * Inserts a single row in the Ab6323s00 table.
	 *
	 * @param ab6323s00
	 *            Ab6323s00
	 * @return Ab6323s00
	 */
	@Transactional(rollbackFor = Throwable.class)
	public Alojamiento add(Alojamiento ab6323s00) {
		return this.alojamientoDao.add(ab6323s00);
	}

	/**
	 * Updates a single row in the Ab6323s00 table.
	 *
	 * @param ab6323s00
	 *            Ab6323s00
	 * @return Ab6323s00
	 */
	@Transactional(rollbackFor = Throwable.class)
	public Alojamiento update(Alojamiento ab6323s00) {
		return this.alojamientoDao.update(ab6323s00);
	}

	/**
	 * Finds a single row in the Ab6323s00 table.
	 *
	 * @param ab6323s00
	 *            Ab6323s00
	 * @return Ab6323s00
	 */
	public Alojamiento find(Alojamiento ab6323s00) {
		return (Alojamiento) this.alojamientoDao.find(ab6323s00);
	}

	/**
	 * Deletes a single row in the Ab6323s00 table.
	 *
	 * @param ab6323s00
	 *            Ab6323s00
	 */
	@Transactional(rollbackFor = Throwable.class)
	public void remove(Alojamiento ab6323s00, Integer idEstablecimiento) {

		// Borramos primero habitaciones/aloj y aseos/aloj asociados al
		// alojamiento
		this.habitacionAlojamientoService.deleteByIdAlojamiento(ab6323s00.getIdAlojamiento());
		this.aseoAlojamientoService.deleteByIdAlojamiento(ab6323s00.getIdAlojamiento());
		this.alojamientoDao.remove(ab6323s00);

		// Long numUnidades =
		// this.alojamientoDao.getTotalAlojamientosByIdEstablecimiento(ab6323s00);
		// actualizamos totales de la tabla
		EstablecimientoData establecimientoData = new EstablecimientoData(
				ab6323s00.getEstablecimientoData().getIdEstablecimiento());

		this.establecimientoDataService.updateTotalesHoteles(establecimientoData);

		// if (null != ab6323s00.getTipoAlojamiento() &&
		// !"".equals(ab6323s00.getTipoAlojamiento())) {
		//
		// if ("A".equals(ab6323s00.getTipoAlojamiento())) {
		//
		// establecimientoData =
		// this.establecimientoDataService.updateEstDataNumApartamentos(establecimientoData,
		// numUnidades);
		//
		// } else if ("E".equals(ab6323s00.getTipoAlojamiento())) {
		//
		// establecimientoData =
		// this.establecimientoDataService.updateEstDataNumEstudios(establecimientoData,
		// numUnidades);
		// } else {
		//
		// establecimientoData =
		// this.establecimientoDataService.updateEstDataNumConjuntos(establecimientoData,
		// numUnidades);
		//
		// }
		//
		// }
	}

	/**
	 * Finds a list of rows in the Ab6323s00 table.
	 *
	 * @param ab6323s00
	 *            Ab6323s00
	 * @param jqGridRequestDto
	 *            JQGridRequestDto
	 * @return List<Ab6323s00>
	 */
	public List<Alojamiento> findAll(Alojamiento ab6323s00, TableRequestDto jqGridRequestDto) {
		return (List<Alojamiento>) this.alojamientoDao.findAll(ab6323s00, jqGridRequestDto);
	}

	/**
	 * Finds rows in the Ab6323s00 table using like.
	 *
	 * @param ab6323s00
	 *            Ab6323s00
	 * @param jqGridRequestDto
	 *            JQGridRequestDto
	 * @param startsWith
	 *            Boolean
	 * @return List<Ab6323s00>
	 */
	public List<Alojamiento> findAllLike(Alojamiento ab6323s00, TableRequestDto jqGridRequestDto, Boolean startsWith) {
		return (List<Alojamiento>) this.alojamientoDao.findAllLike(ab6323s00, jqGridRequestDto, startsWith);
	}

	/*
	 * OPERACIONES RUP_TABLE
	 */

	/**
	 * Removes rows from the Ab6323s00 table.
	 *
	 * @param filterAb6323s00
	 *            Ab6323s00
	 * @param jqGridRequestDto
	 *            JQGridRequestDto
	 * @param startsWith
	 *            Boolean
	 */
	public void removeMultiple(Alojamiento filterAb6323s00, TableRequestDto jqGridRequestDto, Boolean startsWith) {
		this.alojamientoDao.removeMultiple(filterAb6323s00, jqGridRequestDto, startsWith);
	}

	/**
	 * Filter method in the Ab6323s00 table.
	 *
	 * @param filterAb6323s00
	 *            Ab6323s00
	 * @param jqGridRequestDto
	 *            JQGridRequestDto
	 * @param startsWith
	 *            Boolean
	 * @return JQGridResponseDto<Ab6323s00>
	 */
	public TableResponseDto<Alojamiento> filter(Alojamiento filterAb6323s00, TableRequestDto jqGridRequestDto,
			Boolean startsWith) {
		List<Alojamiento> listaAb6323s00 = this.alojamientoDao.findAllLike(filterAb6323s00, jqGridRequestDto, false);

		for (Alojamiento alojamiento : listaAb6323s00) {

			alojamiento.setTotalPlazas(alojamiento.getNumPlazasDormitorio() * alojamiento.getNumUnidades());

			if (null != alojamiento.getTipoAlojamiento() && !"".equals(alojamiento.getTipoAlojamiento())) {

				if ("A".equals(alojamiento.getTipoAlojamiento())) {
					alojamiento.setDescTipoAlojamiento(
							appMessageSource.getMessage("apartamento", null, LocaleContextHolder.getLocale()));
				} else if ("E".equals(alojamiento.getTipoAlojamiento())) {
					alojamiento.setDescTipoAlojamiento(
							appMessageSource.getMessage("estudio", null, LocaleContextHolder.getLocale()));
				} else {
					alojamiento.setDescTipoAlojamiento(
							appMessageSource.getMessage("conjunto", null, LocaleContextHolder.getLocale()));
				}

			}

			if (alojamiento != null && alojamiento.getAccesibilidad() != null) {

				if (alojamiento.getAccesibilidad() > 0) {

					alojamiento.setDescAccesibilidad(
							appMessageSource.getMessage("afirmativo", null, LocaleContextHolder.getLocale()));

				} else {
					alojamiento.setDescAccesibilidad(
							appMessageSource.getMessage("negativo", null, LocaleContextHolder.getLocale()));
				}
			}

		}
		Long recordNum = this.alojamientoDao
				.findAllLikeCount(filterAb6323s00 != null ? filterAb6323s00 : new Alojamiento(), false);
		if (jqGridRequestDto.getMultiselection().getSelectedIds() != null) {
			List<TableRowDto<Alojamiento>> reorderSelection = this.alojamientoDao.reorderSelection(filterAb6323s00,
					jqGridRequestDto, startsWith);
			return new TableResponseDto<Alojamiento>(jqGridRequestDto, recordNum, listaAb6323s00, reorderSelection);
		}
		return new TableResponseDto<Alojamiento>(jqGridRequestDto, recordNum, listaAb6323s00);
	}

	/**
	 * Searches rows in the Ab6323s00 table.
	 *
	 * @param filterAb6323s00
	 *            Ab6323s00
	 * @param searchAb6323s00
	 *            Ab6323s00
	 * @param jqGridRequestDto
	 *            JQGridRequestDto
	 * @param startsWith
	 *            Boolean
	 * @return List<TableRowDto<Ab6323s00>>
	 */
	public List<TableRowDto<Alojamiento>> search(Alojamiento filterAb6323s00, Alojamiento searchAb6323s00,
			TableRequestDto jqGridRequestDto, Boolean startsWith) {
		return this.alojamientoDao.search(filterAb6323s00, searchAb6323s00, jqGridRequestDto, startsWith);
	}

	/**
	 * Reorder the selection made in Ab6323s00 table.
	 *
	 * @param filterAb6323s00
	 *            Ab6323s00
	 * @param jqGridRequestDto
	 *            JQGridRequestDto
	 * @param startsWith
	 *            Boolean
	 * @return Object
	 */
	public List<TableRowDto<Alojamiento>> reorderSelection(Alojamiento filterAb6323s00,
			TableRequestDto jqGridRequestDto, Boolean startsWith) {
		return this.alojamientoDao.reorderSelection(filterAb6323s00, jqGridRequestDto, startsWith);
	}

	/*
	 * OPERACIONES RUP_TABLE JERARQUIA
	 */

	/**
	 * Finder method in the hierarchical the Ab6323s00 table.
	 *
	 * @param filterAb6323s00
	 *            Ab6323s00
	 * @param jqGridRequestDto
	 *            JQGridRequestDto
	 * @param startsWith
	 *            Boolean
	 * @return JQGridResponseDto<JerarquiaDto<Ab6323s00>>
	 */
	public TableResponseDto<JerarquiaDto<Alojamiento>> jerarquia(Alojamiento filterAb6323s00,
			TableRequestDto jqGridRequestDto, Boolean startsWith) {
		List<JerarquiaDto<Alojamiento>> listaAb6323s00 = this.alojamientoDao.findAllLikeJerarquia(filterAb6323s00,
				jqGridRequestDto);
		Long recordNum = this.alojamientoDao.findAllLikeCountJerarquia(filterAb6323s00, jqGridRequestDto);
		return new TableResponseDto<JerarquiaDto<Alojamiento>>(jqGridRequestDto, recordNum, listaAb6323s00);
	}

	/**
	 * Finder method for siblings rows in the hierarchical the Ab6323s00 table.
	 *
	 * @param filterAb6323s00
	 *            Ab6323s00
	 * @param jqGridRequestDto
	 *            JQGridRequestDto
	 * @return JQGridResponseDto<JerarquiaDto<Ab6323s00>>
	 */
	public TableResponseDto<JerarquiaDto<Alojamiento>> jerarquiaChildren(Alojamiento filterAb6323s00,
			TableRequestDto jqGridRequestDto) {
		TableResponseDto<JerarquiaDto<Alojamiento>> jqGridResponseDto = new TableResponseDto<JerarquiaDto<Alojamiento>>();
		jqGridResponseDto.addAdditionalParam(TableResponseDto.CHILDREN,
				this.alojamientoDao.findAllChild(filterAb6323s00, jqGridRequestDto));
		return jqGridResponseDto;
	}

	@Override
	public void findHabitacionAlojamientos(List<Alojamiento> alojamientos) {
		for (Alojamiento alojamiento : alojamientos) {
			HabitacionAlojamiento filter = new HabitacionAlojamiento();
			filter.setAlojamiento(new Alojamiento(alojamiento.getIdAlojamiento()));
			List<HabitacionAlojamiento> habitaciones = this.habitacionAlojamientoService.findAll(filter, null);
			alojamiento.setListHabitacionAlojamiento(habitaciones);
		}
	}

	@Override
	public void findAseosAlojamientos(List<Alojamiento> alojamientos) {
		for (Alojamiento alojamiento : alojamientos) {
			AseoAlojamiento filter = new AseoAlojamiento();
			filter.setAlojamiento(new Alojamiento(alojamiento.getIdAlojamiento()));
			List<AseoAlojamiento> habitaciones = this.aseoAlojamientoService.findAll(filter, null);
			alojamiento.setListAseoAlojamiento(habitaciones);
		}
	}

	@Override
	@Transactional(rollbackFor = Throwable.class)
	public void updateHabitacionesAlojamientos(Alojamiento alojamiento, String usuario) {
		List<HabitacionAlojamiento> habitacionesAlojamiento = alojamiento.getListHabitacionAlojamiento();
		if (habitacionesAlojamiento != null) {
			for (HabitacionAlojamiento habitacionAlojamiento : habitacionesAlojamiento) {
				habitacionAlojamiento.setUsuarioUltmodificacion(usuario);
				habitacionAlojamiento.setFechaUltmodificacion(new Date());
				this.habitacionAlojamientoService.update(habitacionAlojamiento);
			}
		}
	}

	@Override
	@Transactional(rollbackFor = Throwable.class)
	public void updatedAseosAlojamientos(Alojamiento alojamiento, String usuario) {
		List<AseoAlojamiento> aseosAlojamiento = alojamiento.getListAseoAlojamiento();
		if (aseosAlojamiento != null) {
			for (AseoAlojamiento aseoAlojamiento : aseosAlojamiento) {
				aseoAlojamiento.setUsuarioUltmodificacion(usuario);
				aseoAlojamiento.setFechaUltmodificacion(new Date());
				this.aseoAlojamientoService.update(aseoAlojamiento);
			}
		}
	}

	@Override
	@Transactional(rollbackFor = Throwable.class)
	public Alojamiento save(Alojamiento ab6323s00) {

		if (null != ab6323s00.getIdAlojamiento() && ab6323s00.getIdAlojamiento() > 0) {

			ab6323s00 = this.update(ab6323s00);

		} else {

			ab6323s00 = this.add(ab6323s00);

		}

		// actualizamos totales de la tabla
		EstablecimientoData establecimientoData = new EstablecimientoData(
				ab6323s00.getEstablecimientoData().getIdEstablecimiento());

		this.establecimientoDataService.updateTotalesHoteles(establecimientoData);

		return ab6323s00;

	}

	@Override
	public Long getTotalAlojAptosByIdEst(Integer idEstablecimiento) {
		return this.alojamientoDao.getTotalAlojAptosByIdEst(idEstablecimiento);
	}

	@Override
	public Long getTotalAlojEstudiosByIdEst(Integer idEstablecimiento) {
		return this.alojamientoDao.getTotalAlojEstudiosByIdEst(idEstablecimiento);
	}

	@Override
	public Long getTotalAlojConjuntosByIdEst(Integer idEstablecimiento) {
		return this.alojamientoDao.getTotalAlojConjuntosByIdEst(idEstablecimiento);
	}

	@Override
	public Long getTotalUnidadesResumen(Integer idEstablecimiento, List<String> filter) {
		return this.alojamientoDao.getTotalUnidadesResumen(idEstablecimiento, filter);
	}

	@Override
	public Long getTotalUnidadesDetalle(Integer idEstablecimiento, List<String> filter) {
		return this.alojamientoDao.getTotalUnidadesDetalle(idEstablecimiento, filter);
	}

	@Override
	public Long getTotalPlazasResumen(Integer idEstablecimiento, List<String> filter) {
		return this.alojamientoDao.getTotalPlazasResumen(idEstablecimiento, filter);
	}

	@Override
	public Long getTotalPlazasDetalle(Integer idEstablecimiento, List<String> filter) {
		return this.alojamientoDao.getTotalPlazasDetalle(idEstablecimiento, filter);
	}

	@Override
	public void addMasivo(List<Alojamiento> listaAlojamientos, List<HabitacionAlojamiento> listaHabitacionAlojamiento,
			List<AseoAlojamiento> listaAseosAlojamiento) {
		for (Alojamiento alojamiento : listaAlojamientos) {

			Alojamiento alojamientoInsertado = new Alojamiento();

			if (null != alojamiento.getIdAlojamiento()) {
				alojamientoInsertado = this.alojamientoDao.update(alojamiento);
			} else {
				alojamientoInsertado = this.alojamientoDao.addMasivos(alojamiento);
			}

			for (HabitacionAlojamiento habitacionAlojamiento : listaHabitacionAlojamiento) {
				if (alojamientoInsertado.getTipoAlojamiento() != Constantes.TipoAlojamientoEnum.ESTUDIO
						.getIdTipoAlojamiento()
						&& alojamientoInsertado.getNumAlojamiento()
								.equals(habitacionAlojamiento.getAlojamiento().getNumAlojamiento())) {
					habitacionAlojamiento.getAlojamiento().setIdAlojamiento(alojamientoInsertado.getIdAlojamiento());

					TipoHabitacion tipoHabitacion = new TipoHabitacion();
					TipoAseo tipoAseo = new TipoAseo();

					tipoHabitacion.setDescTipoEs(habitacionAlojamiento.getDescTipoHab());
					List<TipoHabitacion> listaTipoHabitacion = tipoHabitacionService.findAllLike(tipoHabitacion, null,
							false);
					if (!listaTipoHabitacion.isEmpty()) {
						habitacionAlojamiento.setTipoHabitacion(listaTipoHabitacion.get(0));
					}
					tipoAseo.setDescTipoEs(habitacionAlojamiento.getDescTipoAseo());
					List<TipoAseo> listaTipoAseo = tipoAseoService.findAllLike(tipoAseo, null, false);
					if (!listaTipoAseo.isEmpty()) {
						habitacionAlojamiento.setTipoAseo(listaTipoAseo.get(0));
					}

					if (null != habitacionAlojamiento.getIdHabitacionAlo()) {
						habitacionAlojamientoService.update(habitacionAlojamiento);
					} else {
						habitacionAlojamientoService.add(habitacionAlojamiento);
					}
				}
			}
			for (AseoAlojamiento aseoAlojamiento : listaAseosAlojamiento) {
				if (alojamientoInsertado.getNumAlojamiento()
						.equals(aseoAlojamiento.getAlojamiento().getNumAlojamiento())) {
					aseoAlojamiento.getAlojamiento().setIdAlojamiento(alojamientoInsertado.getIdAlojamiento());

					TipoAseo tipoAseo = new TipoAseo();

					tipoAseo.setDescTipoEs(aseoAlojamiento.getDescTipoAseo());
					List<TipoAseo> listaTipoAseo = tipoAseoService.findAllLike(tipoAseo, null, false);
					if (!listaTipoAseo.isEmpty()) {
						aseoAlojamiento.setTipoAseo(listaTipoAseo.get(0));
					}
					if (null != aseoAlojamiento.getIdAseoAlo()) {
						aseoAlojamientoService.update(aseoAlojamiento);
					} else {
						aseoAlojamientoService.add(aseoAlojamiento);
					}
				}
			}
		}
	}

}
