package com.ejie.aa20b.control;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import com.ejie.aa20b.ldap.Aa20bDepartamentoXLNET;
import com.ejie.aa20b.ldap.Aa20bServicioXLNET;
import com.ejie.aa20b.ldap.SecurityHelpperException;
import com.ejie.aa20b.ldap.SecurityHelpperXLNets;
import com.ejie.aa20b.model.Departamentos;
import com.ejie.aa20b.model.Direcciones;
import com.ejie.aa20b.service.DepartamentosService;
import com.ejie.aa20b.service.DireccionesService;

/**
 * ProcesosXLNETController , 12-11-2015 8:29:39.
 * 
 * @author Angel
 */

@Controller
@RequestMapping(value = "/procesosXLNET")
public class ProcesosXLNETController {

	private static final Logger logger = LoggerFactory
			.getLogger(ProcesosXLNETController.class);

	@Autowired
	private DepartamentosService departamentosService;

	@Autowired
	private DireccionesService direccionesService;

	/**
	 * Method 'getCreateForm'.
	 * 
	 * @param model
	 *            Model
	 * @return String
	 */
	@RequestMapping(value = "maint", method = RequestMethod.GET)
	public String getCreateForm(Model model) {
		ProcesosXLNETController.logger.info("[GET - View] : procesosXLNET");
		return "dptosDireccXLNET";
	}

	/**
	 * Method 'obtenerDptosNuevosXLNET'. Devuelve los departamentos activos de
	 * XLNET
	 * 
	 * 
	 * @return ArrayList<Aa20bDepartamentoXLNET>
	 * @throws SecurityHelpperException
	 */
	@RequestMapping(value = "obtenerDptosNuevosXLNET", method = RequestMethod.POST)
	public @ResponseBody
	ArrayList<Aa20bDepartamentoXLNET> obtenerDptosNuevosXLNET()
			throws SecurityHelpperException {
		logger.info("[GET - View] : obtener Dptos XLNET");

		ArrayList<Aa20bDepartamentoXLNET> listaDptos = new SecurityHelpperXLNets()
				.getDepartamentosYOrganismosXLNETs();

		ArrayList<Aa20bDepartamentoXLNET> listaDptosNuevos = new ArrayList<Aa20bDepartamentoXLNET>();
		// Comprobar que los todos los departamentos están dados de alta en
		// nuestra base de datos.
		Departamentos dpto = new Departamentos();
		for (Aa20bDepartamentoXLNET dptoAux : listaDptos) {
			dpto.setCidepar(dptoAux.getCodigo());
			dpto.setBaja("0");
			if (this.departamentosService.findAll(dpto, null).size() == 0) {
				// No tenemos en la base de datos ese departamento.
				listaDptosNuevos.add(dptoAux);
			}

		}

		return listaDptosNuevos;

	}

	/**
	 * Method 'obtenerDptosBajaXLNET'. Devuelve los departamentos activos de
	 * XLNET
	 * 
	 * 
	 * @return ArrayList<Departamentos>
	 * @throws SecurityHelpperException
	 */
	@RequestMapping(value = "obtenerDptosBajaXLNET", method = RequestMethod.POST)
	public @ResponseBody
	ArrayList<Departamentos> obtenerDptosBajaXLNET()
			throws SecurityHelpperException {
		logger.info("[GET - View] : obtener Dptos XLNET");

		// Lista de departamentos de XLNET
		ArrayList<Aa20bDepartamentoXLNET> listaDptos = new SecurityHelpperXLNets()
				.getDepartamentosYOrganismosXLNETs();

		// Lista de departamentos de alta en AA20B
		Departamentos filtro = new Departamentos();
		filtro.setBaja("0");
		List<Departamentos> depint = this.departamentosService.findAll(filtro,
				null);

		// Recoger los departamentos que no estan de alta en XLNET y están de
		// alta en nuestra aplicación
		ArrayList<Departamentos> departamentosBaja = calcularDepartamentosBaja(
				listaDptos, depint);

		return departamentosBaja;

	}

	/**
	 * Compara los departamentos xlents, con los departamentos internos para
	 * saber cuales hay que dar de baja
	 * 
	 * @param departamentosXlnet
	 * @param departamentosInternos
	 * @return
	 */
	private ArrayList<Departamentos> calcularDepartamentosBaja(
			ArrayList<Aa20bDepartamentoXLNET> departamentosXlnet,
			List<Departamentos> departamentosInternos) {

		ArrayList<Departamentos> departamentoBaja = new ArrayList<Departamentos>();
		Iterator<Aa20bDepartamentoXLNET> iter = departamentosXlnet.iterator();
		Iterator<Departamentos> iter2 = departamentosInternos.iterator();
		// Recorremos el primer array para obtener los que hay que poner de baja

		Aa20bDepartamentoXLNET dep;
		Departamentos dep2;
		boolean encontrado = true;
		while (iter2.hasNext()) {
			dep2 = iter2.next();
			iter = departamentosXlnet.iterator();
			while (iter.hasNext()) {
				dep = iter.next();
				encontrado = false;
				if (dep.getCodigo().trim().equals(dep2.getCidepar() + "")) {
					encontrado = true;
					break;
				}
			}
			if (!encontrado)
				departamentoBaja.add(dep2);
		}
		return departamentoBaja;
	}

	/**
	 * Method 'actualizarDptosXLNET'. Da de alta los nuevos departamentos y pone
	 * de baja los que no estan en XLNET
	 * 
	 * 
	 * @return Boolean
	 * @throws SecurityHelpperException
	 */
	@RequestMapping(value = "actualizarDptosXLNET", method = RequestMethod.POST)
	public @ResponseBody
	Boolean actualizarDptosXLNET() throws SecurityHelpperException {
		logger.info("[GET - View] : obtener Dptos XLNET");

		// Dar de alta los nuevos departamentos
		ArrayList<Aa20bDepartamentoXLNET> nuevosDptos = this
				.obtenerDptosNuevosXLNET();
		// Comprobar que los todos los departamentos están dados de alta en
		// nuestra base de datos.
		Departamentos dpto = new Departamentos();
		Date fechaHoy = new Date();

		for (Aa20bDepartamentoXLNET dptoAux : nuevosDptos) {
			dpto.setCidepar(dptoAux.getCodigo());
			dpto.setBaja("0");
			if (this.departamentosService.findAll(dpto, null).size() == 0) {
				// No tenemos en la base de datos ese departamento. se da de
				// alta
				dpto.setCdepar(dptoAux.getDescC());
				dpto.setEdepar(dptoAux.getDescE());
				dpto.setFeini(fechaHoy);
				this.departamentosService.add(dpto);
			}
		}

		// Poner de baja los departamentos que no estan en XLNET
		// Lista de departamentos de XLNET
		ArrayList<Aa20bDepartamentoXLNET> listaDptos = new SecurityHelpperXLNets()
				.getDepartamentosYOrganismosXLNETs();

		// Lista de departamentos de alta en AA20B
		Departamentos filtro = new Departamentos();
		filtro.setBaja("0");
		List<Departamentos> depint = this.departamentosService.findAll(filtro,
				null);

		// Recoger los departamentos que no estan de alta en XLNET y están de
		// alta en nuestra aplicación
		ArrayList<Departamentos> departamentosBaja = calcularDepartamentosBaja(
				listaDptos, depint);

		Departamentos dptoBaja = new Departamentos();
		for (Departamentos dptoBajaAux : departamentosBaja) {
			dptoBaja.setIddepar(dptoBajaAux.getIddepar());
			dptoBaja.setBaja("1");
			this.departamentosService.darBajaDpto(dptoBaja);

			/**
			 * Por cada departamento que se pone de baja pondremos de baja las
			 * direcciones en la tabla de direcciones
			 */
			List<Direcciones> direcDepar = new ArrayList<Direcciones>();
			direcDepar = this.direccionesService
					.obtenerDireccionesDpto(dptoBajaAux.getIddepar().toString());
			for (Direcciones direcBaja : direcDepar) {
				this.direccionesService.darBajaDirecc(direcBaja);
			}
		}

		return true;
	}

	/**
	 * Method 'obtenerDireccNuevosXLNET'. Devuelve los departamentos activos de
	 * XLNET
	 * 
	 * 
	 * @return ArrayList<Aa20bServicioXLNET>
	 * @throws SecurityHelpperException
	 */
	@RequestMapping(value = "obtenerDireccNuevosXLNET", method = RequestMethod.POST)
	public @ResponseBody
	ArrayList<Aa20bServicioXLNET> obtenerDireccNuevosXLNET()
			throws SecurityHelpperException {
		logger.info("[GET - View] : obtener Direcciones XLNET");

		// Primero se obtienen los departamentos
		ArrayList<Aa20bDepartamentoXLNET> listaDptos = new SecurityHelpperXLNets()
				.getDepartamentosYOrganismosXLNETs();

		SecurityHelpperXLNets sh = new SecurityHelpperXLNets();
		ArrayList<Aa20bServicioXLNET> servs = null;
		ArrayList<Aa20bServicioXLNET> servsTodos = new ArrayList<Aa20bServicioXLNET>();
		for (Aa20bDepartamentoXLNET dptoAux : listaDptos) {
			try {
				// Obtengo las direcciones de XLNET para ese departamento
				servs = sh.getServiciosXLNETs(dptoAux.getCodigo());
				// Obtengo ahora las direcciones en AA20B
				ArrayList<Direcciones> listaDirecciones = (ArrayList<Direcciones>) this.direccionesService
						.obtenerDireccionesDpto(dptoAux.getCodigo());

				servs = calcularCentrosOrganicosNuevos(listaDirecciones, servs,
						true);
				if (servs != null) {
					servsTodos.addAll(servs);
				}

				// model.addAttribute("servicios", servs);
			} catch (SecurityHelpperException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		return servsTodos;

	}

	/**
	 * Method 'obtenerDireccBajaXLNET'. Devuelve los departamentos activos de
	 * XLNET
	 * 
	 * 
	 * @return ArrayList<Direcciones>
	 * @throws SecurityHelpperException
	 */
	@RequestMapping(value = "obtenerDireccBajaXLNET", method = RequestMethod.POST)
	public @ResponseBody
	ArrayList<Direcciones> obtenerDireccBajaXLNET()
			throws SecurityHelpperException {
		logger.info("[GET - View] : obtener Direcciones de baja XLNET");

		// Primero se obtienen los departamentos
		ArrayList<Aa20bDepartamentoXLNET> listaDptos = new SecurityHelpperXLNets()
				.getDepartamentosYOrganismosXLNETs();

		SecurityHelpperXLNets sh = new SecurityHelpperXLNets();
		ArrayList<Aa20bServicioXLNET> servs = null;
		ArrayList<Direcciones> listaReturn = null;
		ArrayList<Direcciones> servsTodos = new ArrayList<Direcciones>();
		for (Aa20bDepartamentoXLNET dptoAux : listaDptos) {
			try {
				// Obtengo las direcciones de XLNET para ese departamento
				servs = sh.getServiciosXLNETs(dptoAux.getCodigo());
				// Obtengo ahora las direcciones en AA20B
				ArrayList<Direcciones> listaDirecciones = (ArrayList<Direcciones>) this.direccionesService
						.obtenerDireccionesDpto(dptoAux.getCodigo());

				listaReturn = calcularCentrosOrganicosBaja(listaDirecciones,
						servs);
				if (listaReturn != null && listaReturn.size() > 0) {
					servsTodos.addAll(listaReturn);
				}

				// model.addAttribute("servicios", servs);
			} catch (SecurityHelpperException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		return servsTodos;

	}

	/**
	 * 
	 * @param listaCentros
	 * @param servs
	 * @param devolverNuevos
	 * @return
	 */
	private ArrayList<Aa20bServicioXLNET> calcularCentrosOrganicosNuevos(
			ArrayList<Direcciones> listaCentros,
			ArrayList<Aa20bServicioXLNET> servsDirecc, boolean devolverNuevos) {
		Iterator<Direcciones> iter = listaCentros.iterator();
		Iterator<Aa20bServicioXLNET> iter2 = servsDirecc.iterator();
		ArrayList<Aa20bServicioXLNET> salidaDirecc = new ArrayList<Aa20bServicioXLNET>();
		Direcciones dep;
		Aa20bServicioXLNET dep2 = null;
		boolean encontrado = true;
		if (listaCentros.size() == 0)
			salidaDirecc = null;
		else {
			while (iter2.hasNext()) {
				dep2 = iter2.next();
				iter = listaCentros.iterator();
				encontrado = false;
				while (iter.hasNext()) {
					dep = iter.next();
					encontrado = false;
					if (dep.getCidir().equals(dep2.getCodigo())) {
						// dep2.setCargado(true);
						encontrado = true;
						break;
					}
				}
				if (!encontrado && devolverNuevos)
					salidaDirecc.add(dep2);
			}
		}
		if (devolverNuevos)
			return salidaDirecc;
		else
			return null;
	}

	/**
	 * Compara las lista de centros de la BD, con la que hay en xlnets, y
	 * devuelve losque hay que dar de baja
	 * 
	 * @param listaCentros
	 * @param servs
	 * @return
	 */
	private ArrayList<Direcciones> calcularCentrosOrganicosBaja(
			ArrayList<Direcciones> listaCentros,
			ArrayList<Aa20bServicioXLNET> servs) {
		ArrayList<Direcciones> listaReturn = new ArrayList<Direcciones>();
		Iterator<Direcciones> iter = listaCentros.iterator();
		Iterator<Aa20bServicioXLNET> iter2 = servs.iterator();
		Direcciones dep = null;
		Aa20bServicioXLNET dep2;
		boolean encontrado = true;
		while (iter.hasNext()) {
			dep = iter.next();
			iter2 = servs.iterator();
			while (iter2.hasNext()) {
				dep2 = iter2.next();
				encontrado = false;
				if (dep.getCidir().equals(dep2.getCodigo())) {
					encontrado = true;
					break;
				}
			}
			if (!encontrado)
				listaReturn.add(dep);
		}
		return listaReturn;
	}

	/**
	 * Method 'actualizarDireccXLNET'. Da de alta las nuevas direcciones y pone
	 * de baja los que no estan en XLNET
	 * 
	 * 
	 * @return Boolean
	 * @throws SecurityHelpperException
	 */
	@RequestMapping(value = "actualizarDireccXLNET", method = RequestMethod.POST)
	public @ResponseBody
	Boolean actualizarDireccXLNET() throws SecurityHelpperException {
		ProcesosXLNETController.logger
				.info("[GET - View] : obtener Direcciones XLNET");

		// Dar de alta los nuevos direcciones
		ArrayList<Aa20bServicioXLNET> nuevosDirecc = this
				.obtenerDireccNuevosXLNET();
		// Comprobar que los todos las direcciones están dados de alta en
		// nuestra base de datos.
		Direcciones direcc = new Direcciones();
		Date fechaHoy = new Date();

		for (Aa20bServicioXLNET direccAux : nuevosDirecc) {
			direcc = new Direcciones();
			direcc.setCidir(direccAux.getCodigo());
			direcc.setBaja("0");
			if (this.direccionesService.findAll(direcc, null).size() == 0) {
				// No tenemos en la base de datos esa direccion. se da de
				// alta
				direcc.setCdir(direccAux.getDescC());
				direcc.setEdir(direccAux.getDescE());
				direcc.setCodestrUs(direccAux.getCodCog());
				direcc.setFeini(fechaHoy);
				// Obtener el iddepar asociado a codigo de departamento que
				// viene de XLNET
				Long idDeparInterno = this.departamentosService
						.obtenerIddepar(direccAux.getDpto());
				direcc.setIddepar(idDeparInterno);
				this.direccionesService.add(direcc);
			}
		}

		// Poner de baja los departamentos que no estan en XLNET
		// Lista de departamentos de XLNET
		ArrayList<Aa20bDepartamentoXLNET> listaDptos = new SecurityHelpperXLNets()
				.getDepartamentosYOrganismosXLNETs();

		SecurityHelpperXLNets sh = new SecurityHelpperXLNets();
		ArrayList<Aa20bServicioXLNET> servs = null;
		Direcciones direccBaja = new Direcciones();
		for (Aa20bDepartamentoXLNET dptoAux : listaDptos) {
			try {
				// Obtengo las direcciones de XLNET para ese departamento
				servs = sh.getServiciosXLNETs(dptoAux.getCodigo());
				// Obtengo ahora las direcciones en AA20B
				ArrayList<Direcciones> listaDirecciones = (ArrayList<Direcciones>) this.direccionesService
						.obtenerDireccionesDpto(dptoAux.getCodigo());

				ArrayList<Direcciones> direccionesBaja = calcularCentrosOrganicosBaja(
						listaDirecciones, servs);
				if (direccionesBaja != null && direccionesBaja.size() > 0) {
					for (Direcciones dptoBajaAux : direccionesBaja) {
						direccBaja.setIddir(dptoBajaAux.getIddir());
						direccBaja.setBaja("1");
						this.direccionesService.darBajaDirecc(direccBaja);
					}
				}

				// model.addAttribute("servicios", servs);
			} catch (SecurityHelpperException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		return true;
	}
}
