package com.ejie.ab79.control.fichaInspeccion;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Locale;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.SessionAttributes;

import com.ejie.ab79.clientesWS.ab61WebService.Usuario;
import com.ejie.ab79.comun.Constantes;
import com.ejie.ab79.model.Inspectores;
import com.ejie.ab79.model.expedientes.Expedientes;
import com.ejie.ab79.model.inspecciones.Inspecciones;
import com.ejie.ab79.model.nora.T17Provincia;
import com.ejie.ab79.service.InspectoresService;
import com.ejie.ab79.service.expedientes.ExpedientesService;
import com.ejie.ab79.service.inspecciones.InspeccionesService;
import com.ejie.x38.control.bind.annotation.RequestJsonBody;
import com.ejie.x38.dto.JerarquiaDto;
import com.ejie.x38.dto.TableRequestDto;
import com.ejie.x38.dto.TableResponseDto;
import com.ejie.x38.dto.TableRowDto;

/**
 * InspectoresController  
 * 
 *  
 */
@SessionAttributes("usuario")
@Controller
@RequestMapping(value = "/inspectores")

public class InspectoresController {

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

	@Autowired
	private InspectoresService inspectoresService;

	@Autowired
	private InspeccionesService inspeccionesService;

	@Autowired
	private ExpedientesService expedientesService;

	@Resource
	private ReloadableResourceBundleMessageSource appMessageSource;

	/*
	 * OPERACIONES CRUD (Create, Read, Update, Delete)
	 * 
	 */

	/**
	 * Operacion CRUD Read. Devuelve el bean correspondiente al identificador
	 * indicado.
	 * 
	 * @param idInspector
	 *            Integer
	 * @return Inspectores Objeto correspondiente al identificador indicado.
	 */
	@RequestMapping(value = "/{idInspector}", method = RequestMethod.GET)
	public @ResponseBody Inspectores get(@PathVariable Integer idInspector) {
		Inspectores inspectores = new Inspectores();
		inspectores.setIdInspector(idInspector);
		inspectores = this.inspectoresService.findByIdInspector(inspectores);
		InspectoresController.logger.info("[GET - findBy_PK] : Obtener Inspectores por PK");
		return inspectores;
	}

	/**
	 * Devuelve una lista de beans correspondientes a los valores de filtrados
	 * indicados en el objeto pasado como parametro.
	 *
	 * @param filterInspectores
	 *            Inspectores Objeto que contiene los parametros de filtrado
	 *            utilizados en la busqueda.
	 * @return List<Inspectores> Lista de objetos correspondientes a la busqueda
	 *         realizada.
	 */
	@RequestMapping(method = RequestMethod.GET)
	public @ResponseBody List<Inspectores> getAll(@ModelAttribute Inspectores filterInspectores) {
		InspectoresController.logger.info("[GET - find_ALL] : Obtener Inspectores por filtro");
		return this.inspectoresService.findAll(filterInspectores, null);
	}

	@RequestMapping(value = "/datosBasicos/{idInspeccion}", method = RequestMethod.GET)
	public @ResponseBody List<Inspectores> getAllDatosBasicos(@ModelAttribute Inspectores filterInspectores,
			@PathVariable Integer idInspeccion) {
		InspectoresController.logger.info("[Datos Basicos] : Obtener Inspectores por filtro");

		Inspecciones inspeccion = new Inspecciones();

		if (idInspeccion != null) {

			inspeccion.setIdInspeccion(idInspeccion);

			inspeccion = this.inspeccionesService.find(inspeccion);
			InspectoresController.logger
					.info("[Datos Basicos] : Inpeccion: " + inspeccion.getIdentificadorInspeccion());

			if (inspeccion.getExpediente() != null && inspeccion.getExpediente().getIdExpediente() != null) {
				Expedientes expedienteProvincia = new Expedientes();
				expedienteProvincia.setIdExpediente(inspeccion.getExpediente().getIdExpediente());
				expedienteProvincia = this.expedientesService.find(expedienteProvincia);
				InspectoresController.logger
						.info("[Datos Basicos] : Expediente de: " + expedienteProvincia.getIdTerritorioHistorico());

				if (expedienteProvincia.getIdTerritorioHistorico() != 0) {
					T17Provincia provinciaExpediente = new T17Provincia();
					provinciaExpediente.setId(String.valueOf(expedienteProvincia.getIdTerritorioHistorico()));
					filterInspectores.setProvincia(provinciaExpediente);
				}
			}
		}

		List<Inspectores> inspectores = this.inspectoresService.findAll(filterInspectores, null);
		InspectoresController.logger.info("[Datos B锟絪icos] : Numero de Inspectores: " + inspectores.size());

		Boolean existe = false;

		for (Inspectores inspectorAux : inspectores) {
			if (inspectorAux.getIdInspector() == (inspeccion.getInspector().getIdInspector())) {
				existe = true;
				break;
			} else {
				existe = false;
			}
		}

		if (!existe) {
			if (inspeccion.getInspector() != null && inspeccion.getInspector().getIdInspector() != null
					&& inspeccion.getInspector().getIdInspector() != 0) {
				Inspectores inspector = new Inspectores();
				inspector.setIdInspector(inspeccion.getInspector().getIdInspector());
				inspector = this.inspectoresService.find(inspector);
				inspectores.add(inspector);
			}
		}

		return inspectores;
	}

	@RequestMapping(value = "/busquedaInspeccion/{incluirDadosDeBaja}", method = RequestMethod.GET)
	public @ResponseBody List<Inspectores> getAllBusquedaInspeccion(@ModelAttribute Inspectores filterInspectores,
			@PathVariable Boolean incluirDadosDeBaja) {
		InspectoresController.logger.info("[GET - find_ALL] : Obtener Inspectores por filtro");

		if (!incluirDadosDeBaja) {
			filterInspectores.setBaja(0);
		}

		List<Inspectores> listaInspectores = this.inspectoresService.findTodosInspectores(filterInspectores, null);

		Locale locale = LocaleContextHolder.getLocale();

		Inspectores inspectorSin = new Inspectores();
		inspectorSin.setIdInspector(0);
		inspectorSin.setNombreInspector(
				appMessageSource.getMessage("busquedaInspecciones.inspector.sinInspector", null, locale));
		listaInspectores.add(inspectorSin);

		Inspectores inspectorTodos = new Inspectores();
		inspectorTodos.setIdInspector(-1);
		inspectorTodos
				.setNombreInspector(appMessageSource.getMessage("busquedaInspecciones.inspector.todos", null, locale));
		listaInspectores.add(inspectorTodos);

		return listaInspectores;
	}

	/**
	 * Operacion CRUD Edit. Modificacion del bean indicado.
	 *
	 * @param inspectores
	 *            Inspectores Bean que contiene la informacion a modificar.
	 * @return Inspectores Bean resultante de la modificacion.
	 */
	@RequestMapping(method = RequestMethod.PUT)
	public @ResponseBody Inspectores edit(@RequestBody Inspectores inspectores,
			@ModelAttribute(value = "usuario") Usuario usuario) {
		inspectores.setUsuarioUltModificacion(usuario.getUsuario());

		String dniSinLetra = inspectores.getDni().substring(0, inspectores.getDni().length() - 1);
		String passwordSinCifrar = dniSinLetra + Constantes.SUFIJO_EJ;
		String passwordCifrada = this.cifrarPassword(passwordSinCifrar);
		inspectores.setPasswordTablet(passwordCifrada);

		Inspectores inspectoresAux = this.inspectoresService.update(inspectores);
		InspectoresController.logger.info("[PUT] : Inspectores actualizado correctamente");
		return inspectoresAux;
	}

	/**
	 * Operacion CRUD Create. Creacion de un nuevo registro a partir del bean
	 * indicado.
	 *
	 * @param inspectores
	 *            Inspectores Bean que contiene la informacion con la que se va
	 *            a crear el nuevo registro.
	 * @return Inspectores Bean resultante del proceso de creacion.
	 */
	@RequestMapping(method = RequestMethod.POST)
	public @ResponseBody Inspectores add(@RequestBody Inspectores inspectores,
			@ModelAttribute(value = "usuario") Usuario usuario) {
		inspectores.setUsuarioRegistro(usuario.getUsuario());

		String dniSinLetra = inspectores.getDni().substring(0, inspectores.getDni().length() - 1);
		String passwordSinCifrar = dniSinLetra + Constantes.SUFIJO_EJ;
		String passwordCifrada = this.cifrarPassword(passwordSinCifrar);
		inspectores.setPasswordTablet(passwordCifrada);

		Inspectores inspectoresAux = this.inspectoresService.add(inspectores);
		InspectoresController.logger.info("[POST] : Inspectores insertado correctamente");
		return inspectoresAux;
	}

	/**
	 * Operacion CRUD Delete. Borrado del registro correspondiente al
	 * identificador especificado.
	 *
	 * @param idInspector
	 *            Integer Identificador del objeto que se desea eliminar.
	 * @return Inspectores Bean eliminado.
	 */
	@RequestMapping(value = "/{idInspector}", method = RequestMethod.DELETE)
	@ResponseStatus(value = HttpStatus.OK)
	public @ResponseBody Inspectores remove(@PathVariable Integer idInspector,
			@ModelAttribute(value = "usuario") Usuario usuario) {
		Inspectores inspectores = new Inspectores();
		inspectores.setIdInspector(idInspector);
		inspectores.setUsuarioUltModificacion(usuario.getUsuario());
		this.inspectoresService.remove(inspectores);
		InspectoresController.logger.info("[DELETE] : Inspectores borrado correctamente");
		return inspectores;
	}

	/*
	 * METODOS COMPONENTE RUP_TABLE
	 * 
	 */

	/**
	 * Metodo de presentacion del RUP_TABLE.
	 * 
	 * @param model
	 *            Model
	 * @return String
	 */
	@RequestMapping(value = "/maint", method = RequestMethod.GET)
	public String getFormEdit(Model model) {
		InspectoresController.logger.info("[GET - View] : inspectores");
		return "inspectores";
	}

	/**
	 * Operacion de filtrado del componente RUP_TABLE.
	 * 
	 * @param filterInspectores
	 *            Inspectores Bean que contiene los parametros de filtrado a
	 *            emplear.
	 * @param tableRequestDto
	 *            Dto que contiene los parametros de configuracion propios del
	 *            RUP_TABLE a aplicar en el filtrado.
	 * @return TableResponseDto<Inspectores> Dto que contiene el resultado del
	 *         filtrado realizado por el componente RUP_TABLE.
	 */
	@RequestMapping(value = "/filter", method = RequestMethod.POST)
	public @ResponseBody TableResponseDto<Inspectores> filter(
			@RequestJsonBody(param = "filter") Inspectores filterInspectores,
			@RequestJsonBody TableRequestDto tableRequestDto) {
		InspectoresController.logger.info("[POST - filter] : Obtener Inspectoress");
		return this.inspectoresService.filter(filterInspectores, tableRequestDto, false);
	}

	/**
	 * Operacion de busqueda del componente RUP_TABLE.
	 * 
	 * @param filterInspectores
	 *            Inspectores Bean que contiene los parametros de filtrado a
	 *            emplear.
	 * @param searchInspectores
	 *            Inspectores Bean que contiene los parametros de busqueda a
	 *            emplear.
	 * @param tableRequestDto
	 *            Dto que contiene los parametros de configuracion propios del
	 *            RUP_TABLE a aplicar en la b煤squeda.
	 * @return TableRowDto<Inspectores> Dto que contiene el resultado de la
	 *         busqueda realizada por el componente RUP_TABLE.
	 */
	@RequestMapping(value = "/search", method = RequestMethod.POST)
	public @ResponseBody List<TableRowDto<Inspectores>> search(
			@RequestJsonBody(param = "filter") Inspectores filterInspectores,
			@RequestJsonBody(param = "search") Inspectores searchInspectores,
			@RequestJsonBody TableRequestDto tableRequestDto) {
		InspectoresController.logger.info("[POST - search] : Buscar Inspectoress");
		return this.inspectoresService.search(filterInspectores, searchInspectores, tableRequestDto, false);
	}

	/**
	 * Borrado multiple de registros
	 * 
	 * @param filterInspectores
	 *            Inspectores Bean que contiene los parametros de filtrado a
	 *            emplear.
	 * @param tableRequestDto
	 *            Dto que contiene los parametros de configuracion propios del
	 *            RUP_TABLE a aplicar en la busqueda.
	 * @return List<String> Lista de los identificadores de los registros
	 *         eliminados.
	 * 
	 */
	@RequestMapping(value = "/deleteAll", method = RequestMethod.POST)
	@ResponseStatus(value = HttpStatus.OK)
	public @ResponseBody List<String> removeMultiple(@RequestJsonBody(param = "filter") Inspectores filterInspectores,
			@RequestJsonBody TableRequestDto tableRequestDto) {
		InspectoresController.logger
				.info("[POST - search] : [POST - removeMultiple] : Eliminar multiples Inspectoress");
		this.inspectoresService.removeMultiple(filterInspectores, tableRequestDto, false);
		InspectoresController.logger.info("All entities correctly deleted!");

		return tableRequestDto.getMultiselection().getSelectedIds();
	}

	/*
	 * METODOS COMPONENTE RUP_TABLE - JERARQUIA
	 */

	/**
	 * Operacion de filtrado del componente RUP_TABLE para presentar los
	 * registros mediante visualizacion jerarquica.
	 * 
	 * @param filterInspectores
	 *            Inspectores Bean que contiene los parametros de filtrado a
	 *            emplear.
	 * @param tableRequestDto
	 *            Dto que contiene los parametros de configuracion propios del
	 *            RUP_TABLE a aplicar en el filtrado.
	 * @return TableResponseDto<JerarquiaDto<Inspectores>> Dto que contiene el
	 *         resultado del filtrado realizado por el componente RUP_TABLE.
	 */
	@RequestMapping(value = "/jerarquia/filter", method = RequestMethod.POST)
	public @ResponseBody TableResponseDto<JerarquiaDto<Inspectores>> jerarquia(
			@RequestJsonBody(param = "filter") Inspectores filterInspectores,
			@RequestJsonBody TableRequestDto tableRequestDto) {
		InspectoresController.logger.info("[POST - jerarquia] : Obtener Inspectoress jerarquia");
		return this.inspectoresService.jerarquia(filterInspectores, tableRequestDto, false);
	}

	/**
	 * Recupera los hijos de los registros desplegados en la visualizacion
	 * jerarquica.
	 * 
	 * @param filterInspectores
	 *            Inspectores Bean que contiene los parametros de filtrado a
	 *            emplear.
	 * @param tableRequestDto
	 *            Dto que contiene los parametros de configuracion propios del
	 *            RUP_TABLE a aplicar en el filtrado.
	 * @return TableResponseDto<JerarquiaDto<Inspectores>> Dto que contiene el
	 *         resultado del filtrado realizado por el componente RUP_TABLE.
	 */
	@RequestMapping(value = "/jerarquiaChildren", method = RequestMethod.POST)
	public @ResponseBody TableResponseDto<JerarquiaDto<Inspectores>> jerarquiaChildren(
			@RequestJsonBody(param = "filter") Inspectores filterInspectores,
			@RequestJsonBody TableRequestDto tableRequestDto) {
		InspectoresController.logger.info("[POST - jerarquia] : Obtener Inspectoress jerarquia - Hijos");
		return this.inspectoresService.jerarquiaChildren(filterInspectores, tableRequestDto);
	}

	/**
	 * EXPORTERS
	 */

	@RequestMapping(value = "/clipboardReport", method = RequestMethod.POST)
	protected @ResponseBody List<Inspectores> getClipboardReport(
			@RequestJsonBody(param = "filter") Inspectores filterInspectores,
			@RequestJsonBody TableRequestDto tableRequestDto) {
		InspectoresController.logger.info("[POST - clipboardReport] : : Copiar multiples usuarios");
		return this.inspectoresService.getMultiple(filterInspectores, tableRequestDto, false);
	}

	/**
	 * M锟絫odo que genera una hoja de excel con los resultados de b锟絪queda de
	 * inspectores.
	 */
	@RequestMapping(value = { "/exportarExcel/{sidx}/{sord}" }, method = RequestMethod.POST)
	public void getExcel(@ModelAttribute Inspectores filterInspectores, @PathVariable String sidx,
			@PathVariable String sord, @ModelAttribute TableRequestDto tableRequestDto, HttpServletRequest request,
			HttpServletResponse response) {
		try {
			List<Inspectores> listaInspectores;

			tableRequestDto.setSidx(sidx);
			tableRequestDto.setSord(sord);

			if (filterInspectores.getDni().equals("")) {
				filterInspectores.setDni(null);
			}
			if (filterInspectores.getNombreInspector().equals("")) {
				filterInspectores.setNombreInspector(null);
			}
			if (filterInspectores.getNumeroInspector().equals("")) {
				filterInspectores.setNumeroInspector(null);
			}
			if (filterInspectores.getUsuarioXlnets().equals("")) {
				filterInspectores.setUsuarioXlnets(null);
			}
			if (filterInspectores.getProvincia().getDsO().equals("")) {
				filterInspectores.getProvincia().setDsO(null);
			}

			listaInspectores = this.inspectoresService.findAllLike(filterInspectores, tableRequestDto, false);

			this.inspectoresService.getExcel(listaInspectores, response);

		} catch (Exception e) {
			InspectoresController.logger.error("[Exportar Excel] ERROR : ", e);
		}
	}

	/**
	 * M閠odo para cifrar la contrase馻 del inspector
	 * 
	 * @param passwordSinCifrar
	 *            String
	 * @return passwordCifrada String
	 */
	public String cifrarPassword(String passwordSinCifrar) {
		String passWordCifrada = "";

		try {
			MessageDigest md = MessageDigest.getInstance("SHA-512");
			byte[] messageDigest = md.digest(passwordSinCifrar.getBytes());
			BigInteger no = new BigInteger(1, messageDigest);
			passWordCifrada = no.toString(16);

			while (passWordCifrada.length() < 32) {
				passWordCifrada = "0" + passWordCifrada;
			}
		}

		catch (NoSuchAlgorithmException e) {
			InspectoresController.logger.error("cifrarPassword ERROR - " + e.getMessage(), e);
		}

		return passWordCifrada;
	}

}
