package com.ejie.ab61.control.plantillas;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.sql.SQLException;
import java.util.List;

import javax.servlet.http.Cookie;
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.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
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.ab61.comun.CargarPropiedades;
import com.ejie.ab61.comun.Constantes;
import com.ejie.ab61.comun.utilidades.PermisosXLNETS;
import com.ejie.ab61.exceptions.Ab61Exception;
import com.ejie.ab61.exceptions.PifException;
import com.ejie.ab61.model.expedientes.RelExpPla;
import com.ejie.ab61.model.origen.Origen;
import com.ejie.ab61.model.plantillas.ParametrosConfig;
import com.ejie.ab61.model.plantillas.Plantillas;
import com.ejie.ab61.model.plantillas.RelPlaCam;
import com.ejie.ab61.model.procedimientos.Procedimientos;
import com.ejie.ab61.model.usuario.Usuario;
import com.ejie.ab61.service.plantillas.ParametrosConfigService;
import com.ejie.ab61.service.plantillas.PlantillasService;
import com.ejie.ab61.service.plantillas.RelPlaCamService;
import com.ejie.ab61.service.serviciosWeb.ServiciosWebService;
import com.ejie.ab61.tramita.adapter.PifAdapterService;
import com.ejie.x38.control.bind.annotation.RequestJsonBody;
import com.ejie.x38.dto.JQGridRequestDto;
import com.ejie.x38.dto.JQGridResponseDto;
import com.ejie.x38.dto.JerarquiaDto;
import com.ejie.x38.dto.TableRowDto;

/**
 * PlantillasController  
 * 
 *  
 */

@Controller
@RequestMapping(value = "/plantillas")
@SessionAttributes("usuario")
public class PlantillasController {

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

	@Autowired
	private PifAdapterService pifAdapterService;

	@Autowired
	private PlantillasService plantillasService;

	@Autowired
	private RelPlaCamService relPlaCamService;

	@Autowired
	private ServiciosWebService serviciosWebService;

	@Autowired
	private ParametrosConfigService parametrosConfigService;

	public static final String TEMP_PATH = CargarPropiedades.getConfigAplicacion("TEMP.DIR");

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

	/**
	 * Operacion CRUD Read. Devuelve el bean correspondiente al identificador
	 * indicado.
	 * 
	 * @param idPlantilla
	 *            Integer
	 * @return Plantillas Objeto correspondiente al identificador indicado.
	 * @throws SQLException
	 */
	@RequestMapping(value = "/{idPlantilla}", method = RequestMethod.GET)
	public @ResponseBody Plantillas get(@PathVariable Integer idPlantilla, Model model) throws SQLException {
		Plantillas plantillas = new Plantillas();
		plantillas.setIdPlantilla(idPlantilla);
		plantillas = this.plantillasService.find(plantillas);
		RelPlaCam camposPlantilla = new RelPlaCam();

		camposPlantilla.setIdDocumento(plantillas.getDocumento().getIdDocumento());
		List<RelPlaCam> campos = this.relPlaCamService.findAll(camposPlantilla, null);
		String camposDesignados = "";
		if (campos != null && !campos.isEmpty()) {
			for (int i = 0; i < campos.size(); i++) {
				camposDesignados += String.valueOf(campos.get(i).getIdCampo()) + ",";
			}
		}
		plantillas.setCampos(camposDesignados);
		if (plantillas.getDocumento().getNombreDocumento() != null
				&& plantillas.getDocumento().getNombreDocumento().length() > 0) {
			plantillas.setTienePlantilla(1);
		} else {
			plantillas.setTienePlantilla(0);
		}

		PlantillasController.logger.info("[GET - findBy_PK] : Obtener Plantillas por PK");

		return plantillas;
	}

	/**
	 * Generamos el documento
	 * 
	 * @param idPlantilla
	 *            Integer
	 * @return Plantillas Objeto correspondiente al identificador indicado.
	 * @throws Ab61Exception
	 * 
	 * 
	 */
	@RequestMapping(value = "/generarDocumento/{folderId}/{idPlantilla}", method = RequestMethod.GET)
	public @ResponseBody String generarDocumento(@PathVariable String folderId, @PathVariable Integer idPlantilla,
			@ModelAttribute(value = "usuario") Usuario usuario) throws Ab61Exception {
		PlantillasController.logger.info("[GET - generarDocumento] : generarDocumento");
		String nombre = usuario.getNombreUsuario();
		String ruta = serviciosWebService.generarDocumentoNegocio(idPlantilla, folderId, Origen.EXPEDIENTE, nombre);
		return ruta;
	}

	/**
	 * Modificamos el documento con el webDav
	 * 
	 * @param idRelExpPla
	 *            Integer
	 * @return RelExpPla Objeto correspondiente al identificador indicado.
	 * @throws PifException
	 */
	@RequestMapping(value = "/modificarDocumento/{idPlantilla}/{folderId}", method = RequestMethod.GET)
	public @ResponseBody String modificarDocumento(@PathVariable String folderId, @PathVariable Integer idPlantilla,
			@ModelAttribute(value = "usuario") Usuario usuario) throws Ab61Exception {
		PlantillasController.logger.info("[GET - modificarDocumento] : modificarDocumento");
		String nombre = usuario.getNombreUsuario();
		String ruta = serviciosWebService.modificarDocumentoNegocio(idPlantilla, folderId, nombre);
		return ruta;
	}

	/**
	 * llama al webService que realiza la tarea indicada
	 * 
	 * @param idPlantilla
	 *            Integer
	 * @param procedureId
	 *            String
	 * @param folderId
	 *            String
	 * @param n38Login
	 *            String
	 * @return String
	 * @throws Ab61Exception
	 */
	@RequestMapping(value = "/aportarDocumento/{idPlantilla}/{procedureId}/{folderId}", method = RequestMethod.GET)
	public @ResponseBody String aportarDocumento(HttpServletRequest httpRequest, @PathVariable Integer idPlantilla,
			@PathVariable String procedureId, @PathVariable String folderId,
			@ModelAttribute(value = "usuario") Usuario usuario) throws Ab61Exception {

		PlantillasController.logger.info("Entrada a aportarDocumento");

		return this.serviciosWebService.aportarDocumentoNegocio(idPlantilla, folderId, procedureId,
				PermisosXLNETS.fncLogin(httpRequest), usuario.getNombreUsuario());
	}

	/**
	 * llama al webService que realiza la tarea indicada
	 * 
	 * @param idPlantilla
	 *            Integer
	 * @param procedureId
	 *            String
	 * @param folderId
	 *            String
	 *
	 * @throws Ab61Exception
	 */
	@RequestMapping(value = "/eliminarDocumento/{idPlantilla}/{folderId}", method = RequestMethod.GET)
	public @ResponseBody String eliminarDocumento(HttpServletRequest httpRequest, @PathVariable Integer idPlantilla,
			@PathVariable String folderId) throws Ab61Exception {

		PlantillasController.logger.info("Eliminar documento");

		return this.serviciosWebService.eliminarDocumentoNegocio(idPlantilla, folderId);
	}

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

	/**
	 * Operacion CRUD Delete. Borrado del registro correspondiente al
	 * identificador especificado.
	 *
	 * @param idPlantilla
	 *            Integer Identificador del objeto que se desea eliminar.
	 * @return Plantillas Bean eliminado.
	 */
	@RequestMapping(value = "/{idPlantilla}", method = RequestMethod.DELETE)
	@ResponseStatus(value = HttpStatus.OK)
	public @ResponseBody Plantillas remove(@PathVariable Integer idPlantilla) {
		Plantillas plantillas = new Plantillas();
		plantillas.setIdPlantilla(idPlantilla);
		this.plantillasService.remove(plantillas);
		PlantillasController.logger.info("[DELETE] : Plantillas borrado correctamente");
		return plantillas;
	}

	/*
	 * 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) {
		PlantillasController.logger.info("[GET - View] : plantillas");
		return "plantillas";
	}

	/**
	 * Metodo de presentacion del RUP_TABLE.
	 * 
	 * @param model
	 *            Model
	 * @return String
	 */
	@RequestMapping(value = "/maint/{idProcedimiento}/{idExpediente}", method = RequestMethod.GET)
	public String getFormEditPlantilla(@PathVariable Integer idProcedimiento, @PathVariable String idExpediente,
			Model model) {
		PlantillasController.logger.info("[GET - View] : plantillas");
		model.addAttribute("idProcedimiento", idProcedimiento);
		model.addAttribute("idExpediente", idExpediente);

		ParametrosConfig parametrosConfig = new ParametrosConfig();
		parametrosConfig.setDescripcion(Constantes.CONFIGURACION_DOCUMENTOS);
		parametrosConfig = this.parametrosConfigService.findByDescripcion(parametrosConfig);

		model.addAttribute("parametroConfig", parametrosConfig.getValor());
		// Al mostrar la modal con las plantillas, si tenemos idExpediente
		// estamos a nivel Expediente y ni no lo tenemos estamos a nivel
		// Convocatoria

		if (!"null".equalsIgnoreCase(idExpediente))
			model.addAttribute("origen", 1);
		else
			model.addAttribute("origen", 2);

		model.addAttribute("plantilla", new Plantillas());
		return "plantillas";
	}

	/**
	 * Metodo de presentacion del RUP_TABLE.
	 * 
	 * @param model
	 *            Model
	 * @return String
	 */
	@RequestMapping(value = "/inicio/buscador/{codAplic}", method = RequestMethod.GET)
	public String getFormEditPlantilla(@PathVariable Integer codAplic, Model model) {
		PlantillasController.logger.info("[GET - View] : plantillas");
		return "plantillas";
	}

	/**
	 * Operacion de filtrado del componente RUP_TABLE.
	 * 
	 * @param filterPlantillas
	 *            Plantillas Bean que contiene los parametros de filtrado a
	 *            emplear.
	 * @param jqGridRequestDto
	 *            Dto que contiene los parametros de configuracion propios del
	 *            RUP_TABLE a aplicar en el filtrado.
	 * @return JQGridResponseDto<Plantillas> Dto que contiene el resultado del
	 *         filtrado realizado por el componente RUP_TABLE.
	 */
	@RequestMapping(value = "/tabla/{IdProcedimiento}/{IdExpediente}/filter", method = RequestMethod.POST)
	public @ResponseBody JQGridResponseDto<Plantillas> filter(
			@RequestJsonBody(param = "filter") Plantillas filterPlantillas, @PathVariable Integer IdProcedimiento,
			@PathVariable Integer IdExpediente, @RequestJsonBody JQGridRequestDto jqGridRequestDto) {
		PlantillasController.logger.info("[POST - filter] : Obtener Plantillass");
		filterPlantillas.setProcedimientos(new Procedimientos(IdProcedimiento));
		RelExpPla relExpPla = new RelExpPla();
		relExpPla.setIdExpediente(IdExpediente);
		filterPlantillas.setRelExpPla(relExpPla);
		return this.plantillasService.filter(filterPlantillas, jqGridRequestDto, false);
	}

	/**
	 * Metodo para llamar al webservice de la AB61 y que me genere el documento
	 * rtf
	 * 
	 * @param model
	 *            Model
	 * @return String
	 * @throws AB61Exception
	 */
	@RequestMapping(value = "/descargarDocumento/{folderId}/{idPlantilla}", method = RequestMethod.GET)
	public @ResponseBody String descargarDocumento(@PathVariable String folderId, @PathVariable Integer idPlantilla)
			throws Ab61Exception {
		PlantillasController.logger.info("[GET - descargarDocumento] : descargarDocumento");
		String aplicacion = Constantes.CODIGO_APLICACION;
		return serviciosWebService.descargarDocumentoNegocio(idPlantilla, folderId, Origen.EXPEDIENTE, aplicacion);

	}

	@RequestMapping(value = "/descargar", method = RequestMethod.POST)
	public @ResponseBody String descargar(HttpServletResponse httpResponse, @ModelAttribute Plantillas plantilla)
			throws Exception {

		String rutaDocumento = plantilla.getRutaDocumento();
		BufferedInputStream contenidoXml = this.pifAdapterService
				.getFile("/" + Constantes.CODIGO_APLICACION + "/" + rutaDocumento);
		int numRead;
		final int bufferSize = 1024;
		byte[] buffer = new byte[bufferSize];
		ByteArrayOutputStream outString = new ByteArrayOutputStream();
		try {
			while ((numRead = contenidoXml.read(buffer)) != -1) {
				outString.write(buffer, 0, numRead);
			}
		} finally {
			contenidoXml.close();
		}
		byte[] strbase64Doc1 = outString.toByteArray();

		// String nombreDocumento =
		// rutaDocumento.substring(rutaDocumento.indexOf("/"));
		String nombreDocumento = rutaDocumento;
		httpResponse.setHeader("Content-Disposition", "attachment; filename=\"" + nombreDocumento + "\"");
		Cookie cookie = new Cookie("fileDownload", "true");
		cookie.setMaxAge(2);
		cookie.setPath("/");
		httpResponse.addCookie(cookie);
		httpResponse.setContentType("application/doc");

		httpResponse.setContentLength(strbase64Doc1.length);
		httpResponse.getOutputStream().write(strbase64Doc1);

		httpResponse.getOutputStream().flush();
		httpResponse.getOutputStream().close();
		return null;
	}

	/**
	 * Operacion de busqueda del componente RUP_TABLE.
	 * 
	 * @param filterPlantillas
	 *            Plantillas Bean que contiene los parametros de filtrado a
	 *            emplear.
	 * @param searchPlantillas
	 *            Plantillas Bean que contiene los parametros de busqueda a
	 *            emplear.
	 * @param jqGridRequestDto
	 *            Dto que contiene los parametros de configuracion propios del
	 *            RUP_TABLE a aplicar en la búsqueda.
	 * @return TableRowDto<Plantillas> Dto que contiene el resultado de la
	 *         busqueda realizada por el componente RUP_TABLE.
	 */
	@RequestMapping(value = "/search", method = RequestMethod.POST)
	public @ResponseBody List<TableRowDto<Plantillas>> search(
			@RequestJsonBody(param = "filter") Plantillas filterPlantillas,
			@RequestJsonBody(param = "search") Plantillas searchPlantillas,
			@RequestJsonBody JQGridRequestDto jqGridRequestDto) {
		PlantillasController.logger.info("[POST - search] : Buscar Plantillass");
		return this.plantillasService.search(filterPlantillas, searchPlantillas, jqGridRequestDto, false);
	}

	/**
	 * Borrado multiple de registros
	 * 
	 * @param filterPlantillas
	 *            Plantillas Bean que contiene los parametros de filtrado a
	 *            emplear.
	 * @param jqGridRequestDto
	 *            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") Plantillas filterPlantillas,
			@RequestJsonBody JQGridRequestDto jqGridRequestDto) {
		PlantillasController.logger.info("[POST - search] : [POST - removeMultiple] : Eliminar multiples Plantillass");
		this.plantillasService.removeMultiple(filterPlantillas, jqGridRequestDto, false);
		PlantillasController.logger.info("All entities correctly deleted!");

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

	/*
	 * METODOS COMPONENTE RUP_TABLE - JERARQUIA
	 */

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

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

	/**
	 * metodo para saber cuantas plantillas tienen asociado el mismo id de
	 * documento
	 * 
	 * 
	 * @return count.
	 */
	@RequestMapping(value = "/obtenerNumPlantillas/{idDocumento}", method = RequestMethod.GET)
	public @ResponseBody Long obtenerNumDocumentosCampo(@PathVariable Integer idDocumento) {
		Long count = this.plantillasService.obtenerNumDocumentosCampo(idDocumento);

		return count;
	}

	@ExceptionHandler(value = { Ab61Exception.class })

	public void handleSQLException(HttpServletRequest request, HttpServletResponse response, Exception ex)

			throws Exception {

		String mensajeError = "";

		if (LocaleContextHolder.getLocale().getLanguage().equalsIgnoreCase(Constantes.Language.CASTELLANO))

			mensajeError = ((Ab61Exception) ex).getFaultInfo().getMensajeCastellano();

		else

			mensajeError = ((Ab61Exception) ex).getFaultInfo().getMensajeEuskera();

		// stated Content-Length

		response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);

		response.setContentType("text/html;charset=UTF-8");

		response.getWriter().write(mensajeError);

		response.flushBuffer();

	}
}
