package com.ejie.ab63.control.expedientes;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
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.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.servlet.ModelAndView;

import com.ejie.ab63.adaptadores.Ab79WebServiceAdaptadorService;
import com.ejie.ab63.comun.Constantes;
import com.ejie.ab63.comun.utilidades.config.Config;
import com.ejie.ab63.model.DispensaEstablecimiento;
import com.ejie.ab63.model.Establecimiento;
import com.ejie.ab63.model.Inspeccion;
import com.ejie.ab63.model.expedientes.Expedientes;
import com.ejie.ab63.model.inicio.InitForm;
import com.ejie.ab63.model.procedimientos.Procedimientos;
import com.ejie.ab63.model.procedimientos.ProcedimientosRelacionados;
import com.ejie.ab63.model.terceros.RelExpTer;
import com.ejie.ab63.model.usuario.Usuario;
import com.ejie.ab63.model.util.ErrorResultAjaxOperation;
import com.ejie.ab63.model.util.ResultAjaxOperation;
import com.ejie.ab63.model.util.SuccessResultAjaxOperation;
import com.ejie.ab63.service.DispensaEstablecimientoService;
import com.ejie.ab63.service.EstablecimientoDataService;
import com.ejie.ab63.util.UtilDate;

/**
 * RelExpTerController  
 * 
 *  
 */

@Controller
@SessionAttributes("usuario")
@RequestMapping(value = "/fichaExpediente")
public class FichaExpedienteController extends ExpedienteBaseContoller {

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

	@Autowired
	private Ab79WebServiceAdaptadorService inspeccionesService;

	@Autowired
	private EstablecimientoDataService establecimientoDataService;

	@Autowired
	private DispensaEstablecimientoService dispensaService;

	@Override
	protected String getCurrentPage() {
		return Constantes.PESTANA_EXPEDIENTE;
	}

	@Override
	protected String getTilesPage() {
		return "datosExpediente";
	}

	@Override
	protected void setCurrentPageModel(Model model, InitForm initForm) {
		if (initForm.isExpedienteOficio() && initForm.isIdentificadorEmpty()) {
			model.addAttribute("showSearchIdentificador", true);
		}
		Inspeccion inspeccion = this.getExpedientesService().getInspectExpedient(initForm.getIdExpediente());
		logger.info("id Inspeccion " + inspeccion + " para el expediente " + initForm.getIdExpediente());
		if (inspeccion != null && inspeccion.getIdInspeccion() != null && inspeccion.getIdInspeccion() > 0) {
			initForm.setIdInspeccionExpediente(new Long(inspeccion.getIdInspeccion()));
		}
		initForm.setEnableUpdateDirecciones(true);
		setListParticipantes(model, initForm);
		Boolean isEnableChangeNreg = false;
		try {
			isEnableChangeNreg = this.getEstablecimientoService().canChangeIdentifiadorExp(initForm.getIdExpediente(),
					initForm.getIdTerceroTitular());
		} catch (Exception e) {
			isEnableChangeNreg = false;
		}
		if ("".equals(initForm.getObservaciones()) || "###".equalsIgnoreCase(initForm.getObservaciones())) {
			DispensaEstablecimiento dispensa = new DispensaEstablecimiento();
			dispensa.setFolderId(initForm.getFolderId());
			if (dispensaService.existsDispensaForExp(initForm.getFolderId())) {
				dispensa = dispensaService.findByExpediente(dispensa);
			}

			String descs = "{0}###{1}"
					.replace("{0}", dispensa.getObservacionesDescEs() == null ? "" : dispensa.getObservacionesDescEs())
					.replace("{1}", dispensa.getObservacionesDescEu() == null ? "" : dispensa.getObservacionesDescEu());
			initForm.setObservaciones(descs);
			initForm.setDispensado(dispensa.getDispensado());
		}
		model.addAttribute("isEnableChangeNreg", isEnableChangeNreg);
	}

	/**
	 * Operacion CRUD Edit. Modificacion del bean indicado.
	 *
	 * @param relExpTer
	 *            RelExpTer Bean que contiene la informacion a modificar.
	 * @return RelExpTer Bean resultante de la modificacion.
	 */
	@RequestMapping(method = RequestMethod.PUT)
	public @ResponseBody RelExpTer edit(@RequestBody RelExpTer relExpTer) {
		RelExpTer relExpTerAux = this.getRelExpTerService().update(relExpTer);
		FichaExpedienteController.logger.info("[PUT] : RelExpTer actualizado correctamente");
		return relExpTerAux;
	}

	/**
	 * Operacion CRUD Create. Creacion de un nuevo registro a partir del bean
	 * indicado.
	 *
	 * @param relExpTer
	 *            RelExpTer Bean que contiene la informacion con la que se va a
	 *            crear el nuevo registro.
	 * @return RelExpTer Bean resultante del proceso de creacion.
	 */
	@RequestMapping(method = RequestMethod.POST)
	public @ResponseBody RelExpTer add(@RequestBody RelExpTer relExpTer) {
		RelExpTer relExpTerAux = this.getRelExpTerService().add(relExpTer);
		FichaExpedienteController.logger.info("[POST] : RelExpTer insertado correctamente");
		return relExpTerAux;
	}

	@RequestMapping(value = "/maint/{idExpediente}", method = RequestMethod.GET)
	public ModelAndView mostrarGetN(Model model, @PathVariable Integer idExpediente,
			@ModelAttribute(value = "initForm") InitForm initForm, Usuario usuario) throws Exception {
		Expedientes expediente = new Expedientes();
		expediente.setIdExpediente(idExpediente);
		expediente = getExpedientesService().find(expediente);
		if (expediente == null) {
			return new ModelAndView("folderError");
		}
		initForm.setFolderId(expediente.getFolderId());

		if (null != expediente.getProcedimientos() && null != expediente.getProcedimientos().getCodProcedureId()
				&& !"".equalsIgnoreCase(expediente.getProcedimientos().getCodProcedureId())) {
			initForm.setProcedureId(expediente.getProcedimientos().getCodProcedureId());
		}
		initForm.setFolderNumber(expediente.getFolderNumber());
		initForm.setTituloExpediente(expediente.getTitulo());

		model.addAttribute("initForm", initForm);

		return new ModelAndView("folderError", "model", model);
	}

	@RequestMapping(value = "/{folderId}", method = { RequestMethod.GET, RequestMethod.POST })
	public ModelAndView accessUrl(Model model, @PathVariable("folderId") String folderId,
			@ModelAttribute(value = "initForm") InitForm initForm, Usuario usuario) throws Exception {
		Expedientes expediente = new Expedientes();
		expediente.setFolderId(folderId);
		expediente = getExpedientesService().findByFolderId(expediente);
		if (expediente == null) {
			return new ModelAndView("folderError");
		}
		initForm.setIdExpediente(expediente.getIdExpediente());

		if (null != expediente.getProcedimientos() && null != expediente.getProcedimientos().getCodProcedureId()
				&& !"".equalsIgnoreCase(expediente.getProcedimientos().getCodProcedureId())) {
			initForm.setProcedureId(expediente.getProcedimientos().getCodProcedureId());
		}
		initForm.setFolderNumber(expediente.getFolderNumber());
		initForm.setTituloExpediente(expediente.getTitulo());

		model.addAttribute("initForm", initForm);

		return mostrar(model, initForm, usuario);
	}

	@RequestMapping(value = "/maint/{idExpediente}", method = RequestMethod.POST)
	public ModelAndView mostrarExp(Model model, @PathVariable Integer idExpediente,
			@ModelAttribute(value = "initForm") InitForm initForm, Usuario usuario) throws Exception {
		initForm.setIdExpediente(idExpediente);

		Expedientes expediente = new Expedientes();
		expediente.setIdExpediente(idExpediente);
		expediente = getExpedientesService().find(expediente);

		if (expediente == null) {
			return new ModelAndView("folderError");
		}

		initForm.setFolderId(expediente.getFolderId());
		initForm.setIdExpedienteOrigen(expediente.getIdExpedienteOrigen());

		if (null != expediente.getProcedimientos() && null != expediente.getProcedimientos().getCodProcedureId()
				&& !"".equalsIgnoreCase(expediente.getProcedimientos().getCodProcedureId())) {
			initForm.setProcedureId(expediente.getProcedimientos().getCodProcedureId());
		}
		initForm.setFolderNumber(expediente.getFolderNumber());
		initForm.setTituloExpediente(expediente.getTitulo());

		model.addAttribute("initForm", initForm);

		return mostrar(model, initForm, usuario);
	}

	@RequestMapping(value = "/maint", method = RequestMethod.GET)
	public ModelAndView mostrarMaint(Model model, @ModelAttribute(value = "initForm") InitForm initForm,
			Usuario usuario) throws Exception {

		return new ModelAndView("folderError");
	}

	/**
	 * @param model
	 *            Model
	 * @param initForm
	 *            initForm
	 * 
	 * @return ModelAndView
	 * @throws Exception
	 */
	@RequestMapping(value = "/maint", method = RequestMethod.POST)
	public ModelAndView mostrarInit(Model model, @ModelAttribute(value = "initForm") InitForm initForm, Usuario usuario)
			throws Exception {

		Properties prop = Config.loadProperties(Constantes.COD_APPL_CONFIG);
		String url = prop.getProperty("urlVerDocumento");
		url = url.replace("[folderID]", initForm.getFolderId());
		model.addAttribute("urlVerDocumentos", url);

		return mostrar(model, initForm, usuario);

	}

	@RequestMapping(value = "/guardar/{idExpediente}", method = RequestMethod.POST)
	public @ResponseBody ResultAjaxOperation guardar(HttpServletRequest request,
			@PathVariable("idExpediente") Integer idExpediente, @ModelAttribute("initForm") InitForm initForm) {
		try {
			// Se guarda la informacion modificada de la ficha
			return super.saveExpediente(initForm, request);
		} catch (Exception e) {
			logger.error("errorGenerico: ", e.getMessage(), e);
			return new ErrorResultAjaxOperation("errorGenerico", e.getMessage());
		}

	}

	@RequestMapping(value = "/procesar/{idExpediente}", method = RequestMethod.POST)
	public @ResponseBody ResultAjaxOperation procesar(HttpServletRequest request,
			@PathVariable("idExpediente") Integer idExpediente, @ModelAttribute("initForm") InitForm initForm,
			@RequestParam(value = "fechaSugerida", required = false) Date fechaSugerida) {
		try {
			if (fechaSugerida != null) {
				initForm.getMapExtraDataForm().put(Constantes.EXTRA_FORM_FECHA_SUGERIDA, fechaSugerida);
			}
			// Se guarda la informacion modificada de la ficha
			return super.save(initForm, request, true);
		} catch (Exception e) {
			logger.error("errorGenerico: ", e.getMessage(), e);
			return new ErrorResultAjaxOperation("errorGenerico", e.getMessage());
		}

	}

	// searchEstablecimiento
	@RequestMapping(value = "/searchEstablecimiento", method = RequestMethod.GET)
	public @ResponseBody List<Establecimiento> searchEstablecimiento(
			@RequestParam(value = "q", required = true) String q,
			@RequestParam(value = "c", required = true) Boolean c) {
		Establecimiento establecimiento = new Establecimiento();
		establecimiento.setAutocompleteEstablecimiento(q);
		establecimiento.setTipoRegistro(Constantes.TIPO_REGISTRO_DEFINITIVO);
		establecimiento.setMostrar(Constantes.ACTIVOS);
		return getEstablecimientoService().findAllLike(establecimiento, null, false);
	}

	@RequestMapping(value = "/pendientes/{idExpediente}", method = RequestMethod.GET)
	public @ResponseBody ResultAjaxOperation checkExpedientes(@PathVariable("idExpediente") Integer idExpediente) {
		List<Expedientes> expedientes = null;
		try {
			expedientes = this.getExpedientesService().findExpedientesPendientesByExpediente(idExpediente);
		} catch (Exception e) {
			return new ErrorResultAjaxOperation("errorGenerico", e.getMessage());
		}
		SuccessResultAjaxOperation success = new SuccessResultAjaxOperation("expPendientes");
		HashMap<String, String> data = new HashMap<String, String>();
		for (Expedientes expediente : expedientes) {
			Integer idExp = expediente.getIdExpediente();
			if (!idExp.equals(idExpediente)) {
				StringBuilder token = new StringBuilder();
				token.append(expediente.getTitulo());
				token.append("#");
				token.append(expediente.getProcedimientos().getDescripcionEs());
				token.append("#");
				token.append(expediente.getProcedimientos().getDescripcionEu());
				token.append("#");
				token.append(expediente.getFolderNumber());
				token.append("#");
				token.append(
						UtilDate.convertirFechaEnString(expediente.getFechaRegistro(), "dd-MM-yyyy", "yyyy-MM-dd"));
				data.put(expediente.getFolderId(), token.toString());
			}
		}
		if (data.isEmpty()) {
			success.setMessage("sinExpPendientes");
		}
		success.setData(data);
		return success;
	}

	@RequestMapping(value = "/inspecciones/{idExpediente}", method = RequestMethod.POST)
	public @ResponseBody ResultAjaxOperation inspecciones(@PathVariable("idExpediente") Integer idExpediente,
			@ModelAttribute(value = "initForm") InitForm initForm,
			@RequestParam(value = "fechaLimite", required = false) Date fechaLimite,
			@RequestParam(value = "o", required = false) String observaciones) {
		try {
			Establecimiento establecimiento = this.getEstablecimientoService()
					.findByIdenticadorEstablecimiento(initForm.getIdentificadorEstablecimiento());
			establecimiento.setIdentificadorEstablecimiento(initForm.getIdentificadorEstablecimiento());
			this.establecimientoDataService.completeEstablecimientoData(establecimiento,
					Constantes.TIPO_REGISTRO_RESUMEN);
			String identInspeccion = inspeccionesService.crearInspeccion(initForm.getFolderId(), establecimiento,
					fechaLimite, observaciones);

			if (identInspeccion != null && identInspeccion.indexOf("Exception") == -1) {
				SuccessResultAjaxOperation successResultAjaxOperation = new SuccessResultAjaxOperation(
						"inspeccionSuccess");

				Inspeccion inspeccion;
				if (Constantes.AB79_RESPONSE_OK.equalsIgnoreCase(identInspeccion)) {
					inspeccion = this.getExpedientesService().getInspectExpedient(idExpediente);
				} else {
					inspeccion = this.getExpedientesService().getInspect(identInspeccion);
				}
				successResultAjaxOperation.getData().put("idInspeccion", String.valueOf(inspeccion.getIdInspeccion()));
				successResultAjaxOperation.getData().put("identInspeccion",
						String.valueOf(inspeccion.getIdentificadorInspeccion()));
				successResultAjaxOperation.setCallback("disableButtonsInspecSuccess");
				return successResultAjaxOperation;
			}
			return new ErrorResultAjaxOperation("errorInspecciones");
		} catch (Exception e) {
			logger.error("errorGenerico: ", e.getMessage(), e);
			return new ErrorResultAjaxOperation("errorInspecciones", e.getMessage());
		}

	}

	@RequestMapping(value = "/origen", method = RequestMethod.GET)
	public @ResponseBody List<Expedientes> findExpedientesOrigen(
			@RequestParam(value = "identificadorEstablecimiento", required = false) String identificadorEstablecimiento) {
		if (identificadorEstablecimiento == null) {
			return new ArrayList<Expedientes>();
		}
		return this.getExpedientesService().findAllExpedientesOrigen(identificadorEstablecimiento);
	}

	@RequestMapping(value = "/origen/{idExpOrigen}", method = RequestMethod.GET)
	public @ResponseBody ResultAjaxOperation findExpedienteOrigen(@PathVariable("idExpOrigen") Integer idExpOrigen) {
		SuccessResultAjaxOperation successResultAjaxOperation = new SuccessResultAjaxOperation("");
		Expedientes exp = this.getExpedientesService().find(new Expedientes(idExpOrigen));
		successResultAjaxOperation.getData().put("idExpedienteOrigen", exp.getIdExpediente().toString());
		successResultAjaxOperation.getData().put("expedienteOrigenFolderId", exp.getFolderId());
		successResultAjaxOperation.getData().put("expedienteOrigenFolderNumber", exp.getFolderNumber());
		successResultAjaxOperation.getData().put("expedienteOrigenTitulo", exp.getTitulo());
		successResultAjaxOperation.getData().put("procedimentosDescripcionEs",
				exp.getProcedimientos().getDescripcionEs());
		successResultAjaxOperation.getData().put("procedimentosDescripcionEu",
				exp.getProcedimientos().getDescripcionEu());

		return successResultAjaxOperation;
	}

	@RequestMapping(value = "/infoPreInscripcion", method = RequestMethod.GET)
	public @ResponseBody ResultAjaxOperation getInfoPreInscripcion(
			@ModelAttribute(value = "initForm") InitForm initForm) {
		SuccessResultAjaxOperation successResultAjaxOperation = new SuccessResultAjaxOperation("");

		String nextNumeroReg = this.getEstablecimientoService().getNewIntetificador(Constantes.TIPO_REGISTRO_DEFINITIVO,
				initForm.getTipoEstablecimiento(), initForm);

		Date fechaSugerida = this.getEstablecimientoService().calcFechaInscricion(initForm.getIdExpediente());

		Establecimiento establecimiento = getEstablecimientoService()
				.findEstablecimientoByIdExpediente(initForm.getIdExpediente());

		if (null != establecimiento && null != establecimiento.getAgenciaData()
				&& StringUtils.isNotBlank(initForm.getTipoEstablecimiento())
				&& Constantes.AGENCIA_VIAJE.equalsIgnoreCase(initForm.getTipoEstablecimiento())
				&& StringUtils.isNotBlank(initForm.getTipoModalidad())
				&& Constantes.ModalidadFijos.AAVV_PRINCIPAL.equalsIgnoreCase(initForm.getTipoModalidad())
				&& StringUtils.isNotBlank(establecimiento.getAgenciaData().getIdOrigenOfiPrincipal())
				&& Constantes.AGENCIA_ORIGEN_OFICINA_PRINCIPAL_CAPV
						.equalsIgnoreCase(establecimiento.getAgenciaData().getIdOrigenOfiPrincipal())) {

			String nextNumCie = this.getAgenciaDataService().getNextNumCie();

			if (StringUtils.isNotBlank(nextNumCie)) {
				successResultAjaxOperation.getData().put(Constantes.KEY_NUM_CIE, nextNumCie);
			}
		}

		successResultAjaxOperation.getData().put(Constantes.KEY_IDENTIFICADOR_DEFINITIVO, nextNumeroReg);
		successResultAjaxOperation.getData().put(Constantes.KEY_FECHA_SUGERIDA,
				UtilDate.convertirEnFechaConHora(fechaSugerida));

		return successResultAjaxOperation;
	}

	@RequestMapping(value = "/inicioOficio/{procedureId}", method = RequestMethod.GET)
	public @ResponseBody List<ProcedimientosRelacionados> findInicioOficio(
			@PathVariable("procedureId") Integer procedureId) {

		Procedimientos procedimiento = new Procedimientos();
		int idProcedimiento = procedureId;
		procedimiento.setIdProcedimiento(idProcedimiento);
		List<ProcedimientosRelacionados> procedimientos = getProcedimientosService().findRelInicioOficio(procedimiento);

		return procedimientos;
	}

	@RequestMapping(value = "/inicioOficio", method = RequestMethod.POST)
	public @ResponseBody ResultAjaxOperation createInicioOficio(@RequestParam("folderId") String folderId,
			@RequestParam("procedureId") String procedureId, HttpServletRequest request) {

		Map<String, String> data = this.getExpedientesService().createExpedienteInicioOficio(folderId,
				Integer.parseInt(procedureId), request);
		if (data.containsKey(Constantes.KEY_AJAX_ERROR)) {
			return new ErrorResultAjaxOperation(data.get(Constantes.KEY_AJAX_ERROR));
		}
		SuccessResultAjaxOperation result = new SuccessResultAjaxOperation("success");
		if (data.containsKey(Constantes.KEY_AJAX_MESSAGE)) {
			result.setMessage(data.get(Constantes.KEY_AJAX_MESSAGE));
			data.remove(Constantes.KEY_AJAX_MESSAGE);
		}
		result.setData(data);
		return result;
	}
}
