package com.rjconsultores.ventaboletos.service.impl;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.rjconsultores.ventaboletos.dao.ConexionRutaConfDAO;
import com.rjconsultores.ventaboletos.entidad.Conexion;
import com.rjconsultores.ventaboletos.entidad.ConexionConf;
import com.rjconsultores.ventaboletos.entidad.ConexionCtrl;
import com.rjconsultores.ventaboletos.entidad.ConexionRutaConf;
import com.rjconsultores.ventaboletos.entidad.ConexionRutaCtrl;
import com.rjconsultores.ventaboletos.entidad.ConexionRutaExcepcionPtoVta;
import com.rjconsultores.ventaboletos.entidad.ConexionRutaExcepcionTipoPtoVta;
import com.rjconsultores.ventaboletos.entidad.ConexionRutaTramoCtrl;
import com.rjconsultores.ventaboletos.entidad.PuntoVenta;
import com.rjconsultores.ventaboletos.entidad.Ruta;
import com.rjconsultores.ventaboletos.entidad.TipoPuntoVenta;
import com.rjconsultores.ventaboletos.service.ConexionConfService;
import com.rjconsultores.ventaboletos.service.ConexionCtrlService;
import com.rjconsultores.ventaboletos.service.ConexionRutaConfService;
import com.rjconsultores.ventaboletos.service.ConexionRutaCtrlService;
import com.rjconsultores.ventaboletos.service.ConexionRutaExcepcionPtoVtaService;
import com.rjconsultores.ventaboletos.service.ConexionRutaExcepcionTipoPtoVtaService;
import com.rjconsultores.ventaboletos.service.ConexionRutaTramoCtrlService;
import com.rjconsultores.ventaboletos.service.ConexionService;
import com.rjconsultores.ventaboletos.utilerias.UsuarioLogado;
import com.rjconsultores.ventaboletos.vo.parada.ConexionRutaConfVO;
import com.rjconsultores.ventaboletos.vo.parada.ConexionRutaCtrlVO;
import com.rjconsultores.ventaboletos.vo.parada.ParadaVOConexionRuta;

@Service("conexionRutaConfService")
public class ConexionRutaConfServiceImpl implements ConexionRutaConfService {

	@Autowired
	private ConexionRutaConfDAO conexionRutaConfDAO;
	
	@Autowired
	private ConexionRutaExcepcionTipoPtoVtaService conexionRutaExcepcionTipoPtoVtaService;
	
	@Autowired
	private ConexionRutaExcepcionPtoVtaService conexionRutaRestricaoPtoVtaService;
	
	@Autowired
	private ConexionRutaCtrlService conexionRutaCtrlService;
	
	@Autowired
	private ConexionRutaTramoCtrlService conexionRutaTramoCtrlService;
	
	@Autowired
	private ConexionCtrlService conexionCtrlService;
	
	@Autowired
	private ConexionConfService conexionConfService;
	
	@Autowired
	private ConexionService conexionService;	

	@Override
	@Transactional
	public ConexionRutaConf suscribir(ConexionRutaConf conexionRutaConf) {

		conexionRutaConf.setUsuarioId(UsuarioLogado.getUsuarioLogado().getUsuarioId());
		conexionRutaConf.setFecmodif(Calendar.getInstance().getTime());
		conexionRutaConf.setActivo(Boolean.TRUE);

		return conexionRutaConfDAO.suscribir(conexionRutaConf);
	}

	@Override
	@Transactional
	public ConexionRutaConf actualizacion(ConexionRutaConf conexionRutaConf) {
		conexionRutaConf.setUsuarioId(UsuarioLogado.getUsuarioLogado().getUsuarioId());
		conexionRutaConf.setFecmodif(Calendar.getInstance().getTime());
		conexionRutaConf.setActivo(Boolean.TRUE);
		return conexionRutaConfDAO.actualizacion(conexionRutaConf);
	}

	@Override
	@Transactional
	public void borrar(ConexionRutaConf conexionRutaTramoCtrl) {

		conexionRutaTramoCtrl.setUsuarioId(UsuarioLogado.getUsuarioLogado().getUsuarioId());
		conexionRutaTramoCtrl.setFecmodif(Calendar.getInstance().getTime());
		conexionRutaTramoCtrl.setActivo(Boolean.FALSE);

		conexionRutaConfDAO.actualizacion(conexionRutaTramoCtrl);

	}

	@Transactional
	@Override
	public void borrar(List<ConexionRutaConf> lsConexionRutaConf) {
		for (ConexionRutaConf conexion : lsConexionRutaConf) {
			borrar(conexion);
		}
	}

	@Override
	@Transactional
	public void suscribirTodos(List<ConexionRutaConf> lsConexionRutaConf) {
		for (ConexionRutaConf conexion : lsConexionRutaConf) {
			suscribir(conexion);
		}
	}

	@Override
	public List<ConexionRutaConf> obtenerTodosActivo() {
		return conexionRutaConfDAO.obtenerTodosActivo();
	}

	@Override
	public List<ConexionRutaConf> buscarPorDescricao(String descricao) {
		return conexionRutaConfDAO.buscarPorDescricao(descricao);
	}

	@Transactional
	@Override
	public ConexionRutaConf obtenerID(Integer id) {
		return conexionRutaConfDAO.obtenerID(id);
	}

	@Override
	@Transactional
	public void excluirConfiguracao(ConexionRutaConf conexion, boolean excluirConexionRutaConf, boolean isConexionGerada) {
		conexionRutaConfDAO.excluirConfiguracao(conexion, UsuarioLogado.getUsuarioLogado().getUsuarioId(), excluirConexionRutaConf, isConexionGerada);
	}

	@Override
	@Transactional
	public ConexionRutaConf salvarConfiguracao(ConexionRutaConf conexionRutaConf, List<TipoPuntoVenta> canalVentas, List<PuntoVenta> puntoVentas,
								   List<ConexionCtrl> conexoesCtrl, List<ConexionRutaCtrlVO> rutas, List<ParadaVOConexionRuta> localidadesCombinadas,
								   boolean isConexionGerada) {
		conexionRutaConf = suscribirOrActualizacion(conexionRutaConf);
		
		salvarCanalVentasRutaCtrl(conexionRutaConf, canalVentas);
		salvarPuntoVentasRutaCtrl(conexionRutaConf, puntoVentas);
		
		if(isConexionGerada) {
			salvarConexionesRutaCtrl(conexionRutaConf, conexoesCtrl, rutas, localidadesCombinadas);
		} else {
			conexionRutaConfDAO.atualizarTempoMinimoEMaximo(conexionRutaConf);
		}
		
		return conexionRutaConf;
	}
	
	private ConexionRutaConf suscribirOrActualizacion(ConexionRutaConf conexion) {
		if(conexion.getConexionRutaConfId() != null) {
			return actualizacion(conexion);
		} else {
			return suscribir(conexion);
		}
	}

	private void salvarCanalVentasRutaCtrl(ConexionRutaConf conexionRutaConf, List<TipoPuntoVenta> canalVentas) {
		for (TipoPuntoVenta tipoPuntoVenta : canalVentas) {
			ConexionRutaExcepcionTipoPtoVta conexionRutaExcepcionPtoVta = new ConexionRutaExcepcionTipoPtoVta();
			conexionRutaExcepcionPtoVta.setTipoPtovta(tipoPuntoVenta);
			conexionRutaExcepcionPtoVta.setConexionRutaConf(conexionRutaConf);
			conexionRutaExcepcionPtoVta = conexionRutaExcepcionTipoPtoVtaService.suscribir(conexionRutaExcepcionPtoVta);
		}
	}
	
	private void salvarPuntoVentasRutaCtrl(ConexionRutaConf conexionRutaConf, List<PuntoVenta> puntoVentas) {
		for (PuntoVenta puntoVenta : puntoVentas) {
			ConexionRutaExcepcionPtoVta conexionRutaExcepcionPtoVta = new ConexionRutaExcepcionPtoVta();
			conexionRutaExcepcionPtoVta.setConexionRutaConf(conexionRutaConf);
			conexionRutaExcepcionPtoVta.setPuntoVenta(puntoVenta);
			conexionRutaExcepcionPtoVta = conexionRutaRestricaoPtoVtaService.suscribir(conexionRutaExcepcionPtoVta);
		}
	}
	
	private void salvarConexionesRutaCtrl(ConexionRutaConf conexionRutaConf, List<ConexionCtrl> conexoesCtrl, List<ConexionRutaCtrlVO> rutas, List<ParadaVOConexionRuta> localidadesCombinadas) {
		List<ConexionRutaCtrl> lsConexionRutaCtrl = new ArrayList<ConexionRutaCtrl>();
		for (ConexionRutaCtrlVO conexionRutaCtrlVO : rutas) {
			ConexionRutaCtrl conexionRutaCtrl = new ConexionRutaCtrl();
			conexionRutaCtrl.setRutaOrigen(new Ruta(conexionRutaCtrlVO.getRutaIdA()));
			conexionRutaCtrl.setRutaDestino(new Ruta(conexionRutaCtrlVO.getRutaIdB()));
			if(conexionRutaCtrlVO.getRutaIdC() != null) {
				conexionRutaCtrl.setRutaDestinoC(new Ruta(conexionRutaCtrlVO.getRutaIdC()));
			}
			conexionRutaCtrl.setConexionRutaConf(conexionRutaConf);
			conexionRutaCtrl = conexionRutaCtrlService.suscribir(conexionRutaCtrl);
			lsConexionRutaCtrl.add(conexionRutaCtrl);
		}
		List<ConexionRutaTramoCtrl> lsConexionRutaTramo = salvarConexionesRutaTramoCtrl(lsConexionRutaCtrl, localidadesCombinadas);
		salvarConexao(conexionRutaConf, conexoesCtrl, lsConexionRutaTramo, localidadesCombinadas);
	}
	
	private List<ConexionRutaTramoCtrl> salvarConexionesRutaTramoCtrl(List<ConexionRutaCtrl> rutasEntidades, List<ParadaVOConexionRuta> localidadesCombinadas) {
		List<ConexionRutaTramoCtrl> lsConexionRutaTramo = new ArrayList<ConexionRutaTramoCtrl>(0);
		for (ParadaVOConexionRuta vo : localidadesCombinadas) {
			ConexionRutaTramoCtrl conexionRutaTramoCtrl = new ConexionRutaTramoCtrl();
			conexionRutaTramoCtrl.setOrigen(vo.getParadaOrigem());
			conexionRutaTramoCtrl.setDestino(vo.getParadaDestino());
			conexionRutaTramoCtrl.setRuta(new Ruta(vo.getRutaId()));
			conexionRutaTramoCtrl.setSecuencia(vo.getSecuencia());
			
			if(vo.getConexionRutaCtrl() != null && vo.getConexionRutaCtrl().getRutaIdC() == null) {
				conexionRutaTramoCtrl.setConexionRutaCtrl(ConexionRutaCtrl.getConexionRutaCtrl(rutasEntidades,
														  vo.getConexionRutaCtrl().getRutaIdA(),
														  vo.getConexionRutaCtrl().getRutaIdB()));
			} else if(vo.getConexionRutaCtrl() != null && vo.getConexionRutaCtrl().getRutaIdC() != null) {
				conexionRutaTramoCtrl.setConexionRutaCtrl(ConexionRutaCtrl.getConexionRutaCtrl(rutasEntidades,
						  vo.getConexionRutaCtrl().getRutaIdA(),
						  vo.getConexionRutaCtrl().getRutaIdB(),
						  vo.getConexionRutaCtrl().getRutaIdC()));
			} else {
				conexionRutaTramoCtrl.setConexionRutaCtrl(ConexionRutaCtrl.getConexionRutaCtrl(rutasEntidades));
			}
			
			conexionRutaTramoCtrl.setValido(true);
			conexionRutaTramoCtrl.setGrupo(vo.getGrupo());
			conexionRutaTramoCtrl = conexionRutaTramoCtrlService.suscribir(conexionRutaTramoCtrl);
			vo.setConexionRutaTramoId(conexionRutaTramoCtrl.getConexionRutaTramoId());
			
			lsConexionRutaTramo.add(conexionRutaTramoCtrl);
		}
		
		return lsConexionRutaTramo;
	}
	
	private void salvarConexao(ConexionRutaConf conexionRutaConf, List<ConexionCtrl> conexoesCtrl, List<ConexionRutaTramoCtrl> lsConexionRutaTramo, List<ParadaVOConexionRuta> localidadesCombinadas) {
		for (ConexionCtrl conexionCtrl : conexoesCtrl) {
			conexionCtrl = conexionCtrlService.suscribir(conexionCtrl);
			salvarConexionesConf(conexionRutaConf, conexionCtrl);
			salvarConexiones(conexionCtrl, lsConexionRutaTramo, localidadesCombinadas);
		}
	}
	
	private void salvarConexionesConf(ConexionRutaConf conexionRutaConf, ConexionCtrl conexionCtrl) {
			ConexionConf conexionConf = new ConexionConf();
			conexionConf.setConexionCtrl(conexionCtrl);
			conexionConf.setGrupo(conexionCtrl.getGrupos());
			conexionConf.setIndisponible(false);
			conexionConf.setTiempoMin(conexionRutaConf.getTiempoMin());
			conexionConf.setTiempoMax(conexionRutaConf.getTiempoMax());
			conexionConf = conexionConfService.suscribir(conexionConf);
	}
	
	private void salvarConexiones(ConexionCtrl conexionCtrl, List<ConexionRutaTramoCtrl> lsConexionRutaTramo, List<ParadaVOConexionRuta> localidadesCombinadas) {
		List<ConexionRutaTramoCtrl> conexionRutaTramoCtrls = recuperarConexionRutaTramoCtrl(conexionCtrl, lsConexionRutaTramo, localidadesCombinadas);
		for (ConexionRutaTramoCtrl conexionRutaTramoCtrl : conexionRutaTramoCtrls) {
			Conexion conexion = new Conexion();
			conexion.setConexionctrlId(conexionCtrl.getConexionctrlId());
			conexion.setOrigenId(conexionRutaTramoCtrl.getOrigen().getParadaId());
			conexion.setDestinoId(conexionRutaTramoCtrl.getDestino().getParadaId());
			conexion.setNumgrupo(conexionRutaTramoCtrl.getGrupo());
			conexion.setNumsecuencia(conexionRutaTramoCtrl.getSecuencia());
			conexion.setRutaId(conexionRutaTramoCtrl.getRuta().getRutaId());
			conexion.setConexionRutaTramoId(conexionRutaTramoCtrl.getConexionRutaTramoId());

			if(conexionRutaTramoCtrl.getConexionCtrl() != null) {
				conexionRutaTramoCtrl.getConexionCtrl().setConexionctrlId(conexionCtrl.getConexionctrlId());
			}
			
			conexion = conexionService.suscribir(conexion);
		}
	}
	
	private List<ConexionRutaTramoCtrl> recuperarConexionRutaTramoCtrl(ConexionCtrl conexionCtrl, List<ConexionRutaTramoCtrl> lsConexionRutaTramo, List<ParadaVOConexionRuta> localidadesCombinadas) {
		List<ConexionRutaTramoCtrl> list = new ArrayList<ConexionRutaTramoCtrl>(0);
		for (ParadaVOConexionRuta trecho: localidadesCombinadas) {
			if(trecho.getConexionCtrl().isOrigemDestinoGrupoIgual(conexionCtrl.getOrigenId(), conexionCtrl.getDestinoId(), conexionCtrl.getGrupos())) {
				ConexionRutaTramoCtrl aux = new ConexionRutaTramoCtrl(trecho.getConexionRutaTramoId());
				Integer idx = lsConexionRutaTramo.indexOf(aux);
				if(idx > -1) {
					ConexionRutaTramoCtrl aux2 = lsConexionRutaTramo.get(idx);
					aux2.setConexionCtrl(trecho.getConexionCtrl());
					list.add(aux2);
				}
			}
		}
		return list;
	}

	@Override
	public ConexionRutaConfVO carregarConexoesCadastradas(Integer conexionrutaconfId) {
		return conexionRutaConfDAO.carregarConexoesCadastradas(conexionrutaconfId);
	}

	@Override
	public List<List<Ruta>> buscarRutasPorConexionConf(Integer conexionRutaConfId) {
		return conexionRutaConfDAO.buscarRutasPorConexionConf(conexionRutaConfId);
	}

	@Override
	public ConexionRutaConf getByIdActivo(Integer conexionRutaConfId) {
		return conexionRutaConfDAO.getByIdActivo(conexionRutaConfId);
	}

}
