package com.ejie.ab79.control.plantillas;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.StringReader;
import java.util.List;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.i18n.LocaleContextHolder;
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.SessionAttributes;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;

import com.ejie.ab79.clientesWS.ab61WebService.Ab61Exception;
import com.ejie.ab79.clientesWS.ab61WebService.IdentificadoresPid;
import com.ejie.ab79.clientesWS.ab61WebService.Origen;
import com.ejie.ab79.clientesWS.ab61WebService.Usuario;
import com.ejie.ab79.comun.Constantes;
import com.ejie.ab79.model.actuaciones.Actuaciones;
import com.ejie.ab79.model.actuaciones.RelActDoc;
import com.ejie.ab79.model.expedientes.Expedientes;
import com.ejie.ab79.model.plantillas.ParametrosConfig;
import com.ejie.ab79.model.plantillas.Plantillas;
import com.ejie.ab79.service.actuaciones.RelActDocService;
import com.ejie.ab79.service.expedientes.ExpedientesService;
import com.ejie.ab79.service.plantillas.ParametrosConfigService;
import com.ejie.ab79.service.plantillas.PlantillasService;
import com.ejie.ab79.webservice.adaptadores.PIFAdaptador;
import com.ejie.ab79.webservice.adaptadores.ab61WebServiceAdaptador;
import com.ejie.x38.control.bind.annotation.RequestJsonBody;
import com.ejie.x38.dto.TableRequestDto;
import com.ejie.x38.dto.TableResponseDto;

/**
 * PlantillasController  
 * 
 *  
 */
@SessionAttributes("usuario")
@Controller
@RequestMapping(value = "/plantillas")

public class PlantillasController {

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

	@Autowired
	private ParametrosConfigService parametrosConfigService;

	@Autowired
	private PlantillasService plantillasService;

	@Autowired
	private ab61WebServiceAdaptador ab61WebServiceAdaptadorService;

	@Autowired
	private PIFAdaptador pifAdapterService;

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

		/*
		 * Sacamos el valor ( 0 , 1 , 2 ) segun descripcion del parametro de
		 * configuracion
		 */
		model.addAttribute("idProcedimiento", idProcedimiento);
		model.addAttribute("idExpediente", idExpediente);
		model.addAttribute("origenPlantilla", Constantes.Plantillas.ORIGEN_EXPEDIENTE);
		model.addAttribute("idActuacionModalPlantillas", idActuacion);

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

		model.addAttribute("parametroConfig", parametrosConfig.getValor());

		boolean esExpedienteCerrado = this.expedientesService.findExpedienteCerrado(new Expedientes(Integer.valueOf(idExpediente)));
		model.addAttribute("esExpedienteCerrado", esExpedienteCerrado);

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

	@RequestMapping(value = "/maint/{idProcedimiento}/{idActuacion}", method = RequestMethod.GET)
	public String getFormEditPlantillaSinExp(@PathVariable Integer idProcedimiento, @PathVariable Integer idActuacion,
			Model model) {
		PlantillasController.logger.info("[GET - View] : plantillas");

		/*
		 * Sacamos el valor ( 0 , 1, 2 ) segun descripcion del parametro de
		 * configuracion
		 */
		model.addAttribute("idProcedimiento", idProcedimiento);
		model.addAttribute("origenPlantilla", Constantes.Plantillas.ORIGEN_INSPECCION);
		model.addAttribute("idActuacionModalPlantillas", idActuacion);

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

		model.addAttribute("parametroConfig", parametrosConfig.getValor());

		//No hay expediente que comprobar por lo que asignamos falso
		model.addAttribute("esExpedienteCerrado", false);
		
		model.addAttribute("plantilla", new 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 = "/filter", method = RequestMethod.POST)
	public @ResponseBody TableResponseDto<Plantillas> filter(
			@RequestJsonBody(param = "filter") Plantillas filterPlantillas,
			@RequestJsonBody TableRequestDto tableRequestDto) {

		PlantillasController.logger.info("[POST - filter] : Obtener Plantillass");

		return this.plantillasService.filter(filterPlantillas, tableRequestDto);

	}

	/**
	 * Metodo para llamar al webservice de la AB61 y que me genere el documento
	 * rtf
	 * 
	 * @param model
	 *            Model
	 * @return String
	 * @throws AB61Exception
	 */
	@RequestMapping(value = "/llamarWebService/generarDocumento/{folderId}/{identificadorInspeccion}/{idPlantilla}", method = RequestMethod.GET)
	public @ResponseBody String generarDocumento(@PathVariable String folderId,
			@PathVariable String identificadorInspeccion, @PathVariable Integer idPlantilla,
			@ModelAttribute(value = "usuario") Usuario usuario) throws Ab61Exception {
		PlantillasController.logger.info("[GET - generarDocumento] : generarDocumentoNegocio");

		String identificador;
		Origen origen;

		if ("0".equals(folderId)) {
			identificador = identificadorInspeccion;
			origen = Origen.INSPECCION;
		} else {
			identificador = folderId;
			origen = Origen.EXPEDIENTE;
		}

		return ab61WebServiceAdaptadorService.generarDocumentoNegocio(idPlantilla, identificador, origen,
				usuario.getUsuario().toLowerCase());

	}

	/**
	 * Metodo para llamar al webservice de la AB61 y que me modifique el
	 * documento rtf
	 * 
	 * @param model
	 *            Model
	 * @return String
	 * @throws AB61Exception
	 */
	@RequestMapping(value = "/llamarWebService/modificarDocumento/{idPlantilla}/{folderId}/{identificadorInspeccion}", method = RequestMethod.GET)
	public @ResponseBody String modificarDocumento(@PathVariable String folderId,
			@PathVariable String identificadorInspeccion, @PathVariable Integer idPlantilla,
			@ModelAttribute(value = "usuario") Usuario usuario) throws Ab61Exception {
		PlantillasController.logger.info("[GET - modificarDocumentoNegocio] : modificarDocumentoNegocio");

		String identificador;

		if ("0".equals(folderId)) {
			identificador = identificadorInspeccion;
		} else {
			identificador = folderId;
		}

		return this.ab61WebServiceAdaptadorService.modificarDocumentoNegocio(idPlantilla, identificador,
				usuario.getUsuario());
	}

	/**
	 * 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 = "/llamarWebService/aportarDocumentoPid/{idPlantilla}/{identificadorInspeccion}/{idActuacion}", method = RequestMethod.GET)
	public @ResponseBody String aportarDocumentoPid(HttpServletRequest httpRequest, @PathVariable Integer idPlantilla,
			@PathVariable String identificadorInspeccion, @PathVariable Integer idActuacion,
			@ModelAttribute(value = "usuario") Usuario usuario) throws Ab61Exception {

		String result = "";

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

		try {
			IdentificadoresPid identificadoresPid = this.ab61WebServiceAdaptadorService.aportarDocumentoPid(idPlantilla,
					identificadorInspeccion, Constantes.CODIGO_APLICACION, usuario.getUsuario());

			RelActDoc relActDoc = new RelActDoc();
			relActDoc.setActuacion(new Actuaciones(idActuacion));
			relActDoc.setEnviadoProSan(Constantes.ENVIADO_PRO_SAN_NO);
			relActDoc.setIdDocumentoSubido(identificadoresPid.getIdDocumentoPid());
			relActDoc.setUsuarioRegistro(usuario.getUsuario());

			this.relActDocService.add(relActDoc);

			result = "ok";
		} catch (Exception e) {
			PlantillasController.logger.error(e.getMessage(), e);

		}

		return result;
	}

	@RequestMapping(value = "/llamarWebService/aportarDocumento/{idPlantilla}/{procedureId}/{folderId}/{idActuacion}", method = RequestMethod.GET)
	public @ResponseBody String aportarDocumento(HttpServletRequest httpRequest, @PathVariable Integer idPlantilla,
			@PathVariable String procedureId, @PathVariable String folderId, @PathVariable Integer idActuacion,
			@ModelAttribute(value = "usuario") Usuario usuario) throws Ab61Exception {

		PlantillasController.logger.info("Entrada a aportarDocumentoPlatea.");
		PlantillasController.logger.info("USUARIO - nombre:" + usuario.getUsuario());
		PlantillasController.logger.info("USUARIO - primer apellido:" + usuario.getPrimerApellido());
		PlantillasController.logger.info("USUARIO - segundo apellido:" + usuario.getSegundoApellido());
		PlantillasController.logger.info("USUARIO - identificador:" + usuario.getIdentificador());
		PlantillasController.logger.info("USUARIO - buzon:" + usuario.getBuzon());

		String xmlRespuesta = this.ab61WebServiceAdaptadorService.aportarDocumentoPlatea(idPlantilla, procedureId,
				folderId, usuario);

		if (idActuacion != 0) {
			try {
				DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
				InputSource src = new InputSource();
				src.setCharacterStream(new StringReader(xmlRespuesta));

				Document doc = builder.parse(src);
				String idDocumentoSubido = doc.getElementsByTagName("idDocumentoSubido").item(0).getTextContent();

				RelActDoc relActDoc = new RelActDoc();
				relActDoc.setActuacion(new Actuaciones(idActuacion));
				relActDoc.setEnviadoProSan(Constantes.ENVIADO_PRO_SAN_NO);
				relActDoc.setIdDocumentoSubido(Integer.parseInt(idDocumentoSubido));
				relActDoc.setUsuarioRegistro(usuario.getUsuario());

				this.relActDocService.add(relActDoc);

			} catch (Exception e) {
				PlantillasController.logger.error(e.getMessage(), e);
			}
		}

		return xmlRespuesta;

	}

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

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

		String identificador;

		if ("0".equals(folderId)) {
			identificador = identificadorInspeccion;
		} else {
			identificador = folderId;
		}

		return ab61WebServiceAdaptadorService.eliminarDocumentoNegocio(idPlantilla, identificador);

	}

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

		return ab61WebServiceAdaptadorService.descargarDocumentoNegocio(idPlantilla, identificador, origen, aplicacion, false);

	}

	@RequestMapping(value = "/llamarWebService/descargarDocumento/{identificadorInspeccion}/{idPlantilla}", method = RequestMethod.GET)
	public @ResponseBody String descargarDocumentoSinExpediente(@PathVariable String identificadorInspeccion,
			@PathVariable Integer idPlantilla) throws Ab61Exception {
		PlantillasController.logger.info("[GET - descargarDocumento] : descargarDocumento");
		String aplicacion = Constantes.CODIGO_APLICACION;
		String identificador = identificadorInspeccion;
		Origen origen = Origen.INSPECCION;

		return ab61WebServiceAdaptadorService.descargarDocumentoNegocio(idPlantilla, identificador, origen, aplicacion, false);

	}

	@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;
		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;
	}

	/**
	 * Captura las excepciones AB61Exception.
	 *
	 */
	@ExceptionHandler(value = { Ab61Exception.class })
	public void handleSQLException(HttpServletRequest request, HttpServletResponse response, Exception ex)
			throws Exception {

		String mensajeError = "";

		if (LocaleContextHolder.getLocale().getLanguage().equalsIgnoreCase(Constantes.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();
	}

	@RequestMapping(value = "tiposPlantillaDeDocumento/{idProcedimiento}", method = RequestMethod.GET)
	public @ResponseBody List<Plantillas> findTiposPlantillaDeDocumento(@PathVariable Integer idProcedimiento) {
		PlantillasController.logger.info("[GET] : Obtener TiposPlantilla de tipo de documento");
		return this.plantillasService.findTiposPlantillaDeDocumento(idProcedimiento);
	}
}
