package com.ejie.ab39a.control;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
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.beans.propertyeditors.CustomDateEditor;
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.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
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.ResponseStatus;
import com.ejie.ab39a.constantes.Constantes;
import com.ejie.ab39a.exceptions.ErrorGenericoException;
import com.ejie.ab39a.model.AccionesPg;
import com.ejie.ab39a.model.Elemento;
import com.ejie.ab39a.model.ElementoCombo;
import com.ejie.ab39a.model.ElementosArbol;
import com.ejie.ab39a.model.ElementosPe;
import com.ejie.ab39a.model.ElementosPg;
import com.ejie.ab39a.model.Entidades;
import com.ejie.ab39a.model.PlanesEstrategicos;
import com.ejie.ab39a.model.PlanesGestion;
import com.ejie.ab39a.seguridad.UsuarioConectado;
import com.ejie.ab39a.seguridad.UtilSeguridad;
import com.ejie.ab39a.service.AccionesPgService;
import com.ejie.ab39a.service.ElementoService;
import com.ejie.ab39a.service.ElementosArbolService;
import com.ejie.ab39a.service.ElementosPgService;
import com.ejie.ab39a.service.ExcelService;
import com.ejie.ab39a.service.PdfService;
import com.ejie.ab39a.service.PlanesEstrategicosService;
import com.ejie.ab39a.service.PlanesGestionService;
import com.ejie.x38.control.bind.annotation.RequestJsonBody;
import com.ejie.x38.dto.JQGridRequestDto;
import com.ejie.x38.dto.JQGridResponseDto;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gfi.utils.UtilDate;
import com.gfi.utils.Utilities;

/**
 * ElementoController.
 * 
 *  
 */

@Controller
@RequestMapping(value = "/elementosArbol")

public class ElementosArbolController {

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

    @Autowired
    private ElementoService elementoService;
    @Autowired
    private ElementosArbolService elementoArbolService;
    @Autowired
    private PlanesEstrategicosService planesEstrategicosService;
    @Autowired
    private PlanesGestionService planesGestionService;
    @Autowired
    private AccionesPgService accionesPgService;
    @Autowired
    private ElementosPgService elementosPgService;
    @Autowired
    private ReloadableResourceBundleMessageSource appMessageSource;
    @Autowired
    private ExcelService excelService;
    @Autowired
    private PdfService pdfService;

    /**
     * Usamos este mÃ©todo para indicarle a Spring el formato que debe usar para serializar las
     * fechas cuando cargamos la entidad en el Model. En el resto de peticiones que devuelven un
     * objeto con la anotaciÃ³n '@ResponseBody' se usan los serializadores de UDA
     *
     * @param binder
     *            WebDataBinder binder
     */
    @InitBinder()
    public void initBinder(WebDataBinder binder) {

        Locale locale = LocaleContextHolder.getLocale();
        DateFormat dateFormat = null;
        if (locale.equals(Constantes.LOCALE_ES)) {
            dateFormat = new SimpleDateFormat(Constantes.ES_DATE_MASK);
        } else {
            dateFormat = new SimpleDateFormat(Constantes.EU_DATE_MASK);
        }
        binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
    }

    /**
     * Operacion CRUD Read. Devuelve el bean correspondiente al identificador indicado.
     * 
     * @param idElemento
     *            Long id elemento
     * @return Elemento Objeto correspondiente al identificador indicado.
     */
    @RequestMapping(value = "/{idElemento}", method = RequestMethod.GET)
    public @ResponseBody Elemento get(@PathVariable Long idElemento) {
        Elemento elemento = new Elemento();
        elemento.setIdElemento(idElemento);
        elemento = this.elementoService.find(elemento);
        ElementosArbolController.logger.info("[GET - findBy_PK] : Obtener Elemento por PK");
        return elemento;
    }

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

    /**
     * lista de tipos de situacion
     * 
     * @return List<TiposReceptores> Lista de objetos correspondientes a la busqueda realizada.
     */
    @RequestMapping(value = "getTiposSituacion", method = RequestMethod.GET)
    public @ResponseBody List<ElementoCombo> getTiposSituacion() {
        ElementosArbolController.logger.info("[GET - find_ALL] : Obtener Tipos Situacion por filtro");
        List<ElementoCombo> lista = new ArrayList<ElementoCombo>();
        lista.add(new ElementoCombo(Constantes.SITUACION1COD, Constantes.SITUACION1ES, Constantes.SITUACION1EU));
        lista.add(new ElementoCombo(Constantes.SITUACION2COD, Constantes.SITUACION2ES, Constantes.SITUACION2EU));
        lista.add(new ElementoCombo(Constantes.SITUACION3COD, Constantes.SITUACION3ES, Constantes.SITUACION3EU));
        return lista;
    }

    /**
     * DEvuelve el tipo de usuario conectado
     * 
     * @return String usuario conectado
     */
    private String devUsuario() {
        String usuario = "";
        UsuarioConectado usuarioConectado = UtilSeguridad.getUsuarioConectado();
        if (usuarioConectado.isTecnicoHps()) {
            usuario = Constantes.USUARIO_HPS;
        } else if (usuarioConectado.isTecnicoEntidad()) {
            usuario = Constantes.USUARIO_TECNICO;
        }
        return usuario;
    }

    /**
     * Devuelve la lista de los elementos del arbol
     *
     * @param idP
     *            Integer id del plan
     * @param model
     *            Model model
     * @param tipo
     *            String tipo plan
     * @param version
     *            Integer version
     * @param consulta
     *            Integer consulta
     * @return String string
     */
    @SuppressWarnings("unchecked")
    @RequestMapping(value = "/arbol/detalle/{idP}/{tipo}/{version}/{consulta}", method = RequestMethod.GET)
    public String buscarArbol(@PathVariable Integer idP, @PathVariable String tipo, @PathVariable Integer version,
            @PathVariable Integer consulta, Model model) {
        ElementosArbolController.logger.info("[GET - find_ALL] : Obtener Elemento por filtro");

        String usuario = devUsuario();
        List<ElementosArbol> lista = new ArrayList<ElementosArbol>();
        List<ElementosArbol> listaElemBorrados = new ArrayList<ElementosArbol>();
        if (tipo.equals(Constantes.TIPO_PLAN_ESTRAT)) {
            PlanesEstrategicos planid = new PlanesEstrategicos();
            planid.setCodplane(idP);
            planid.setCodVersion(version);

            Map<String, Object> mapaDatos = this.elementoArbolService.datosArbolPlanE(planid, consulta);
            PlanesEstrategicos plan = (PlanesEstrategicos) mapaDatos.get("datosPlan");
            lista = (List<ElementosArbol>) mapaDatos.get("lista");
            listaElemBorrados = (List<ElementosArbol>) mapaDatos.get("listaElemBorrados");
            model.addAttribute("datosPlan", plan);
            model.addAttribute("tienePg", (Long) mapaDatos.get("tienePg"));
            model.addAttribute("solicitudTxostena", (Integer) mapaDatos.get("solicitudTxostena"));
        } else {
            PlanesGestion planid = new PlanesGestion();
            planid.setCodplang(idP);
            PlanesGestion plan = this.planesGestionService.find(planid);
            model.addAttribute("datosPlan", plan);
            Map<String, List<AccionesPg>> acciones = this.accionesPgService.buscarAccionesPgArbol(idP);
            model.addAttribute("acciones", acciones);
            lista = this.elementoArbolService.findAllGestion(idP, null);
            model.addAttribute("tienePg", Constantes.LONG_5);
            model.addAttribute("solicitudTxostena", 0);

        }
        Entidades entidad = new Entidades();
        Integer solicInfor = null;
        String usuarioConectado = null;
        if (UtilSeguridad.getUsuarioConectado().isTecnicoEntidad()) {
            usuarioConectado = Constantes.USUARIO_TEC_ENTIDAD;
            entidad = UtilSeguridad.getUsuarioConectado().getTecnicosEntidad().getEntidadPrincipal();
            solicInfor = entidad.getSolicInfor();
        }
        model.addAttribute("solicInfor", solicInfor);
        model.addAttribute("usuarioConectado", usuarioConectado);
        model.addAttribute("listaElemBorrados", listaElemBorrados);
        model.addAttribute("listaElementos", lista.get(0).getHijosArbol());
        model.addAttribute("codPlane", idP);
        model.addAttribute("usuario", usuario);
        model.addAttribute("version", version);
        model.addAttribute("tipoPlan", tipo);
        model.addAttribute("consulta", consulta);
        return "elementosArbol";
    }

    /**
     * Guardar el helburu del elemento
     * 
     * @param idElemento
     *            Long id del elemento
     * @param titulo
     *            String titulo
     * @param tituloCas
     *            String titulo titulo castellano
     * @param nivel
     *            Long nivel
     * @param codPlane
     *            Long codigo de plan
     * 
     * @return String string
     */
    @RequestMapping(value = { "/guardarHelburu" }, method = RequestMethod.POST)
    public @ResponseBody String guardarHelburu(@RequestJsonBody(param = "idElemento") Long idElemento,
            @RequestJsonBody(param = "titulo") String titulo, @RequestJsonBody(param = "tituloCas") String tituloCas,
            @RequestJsonBody(param = "nivel") Long nivel, @RequestJsonBody(param = "codPlane") Long codPlane) {
        ElementosArbol elem = new ElementosArbol();
        elem.setHelburuA(titulo);
        elem.setIdElementoA(idElemento);
        elem.setNivelA(nivel);
        elem.setHelburucasA(tituloCas);
        elem.setCodPlaneA(codPlane);
        this.elementoArbolService.guardarHelburu(elem);
        ElementosArbolController.logger.info("[PUT] : Helburu guardado correctamente");
        return "OK";
    }

    /**
     * Guardar el titulo pg del elemento
     * 
     * @param idElemento
     *            Long id del elemento
     * @param titulo
     *            String titulo
     * @param tituloCas
     *            String titulo titulo castellano
     * 
     * @return String string
     */
    @RequestMapping(value = { "/guardarTituloPG" }, method = RequestMethod.POST)
    public @ResponseBody String guardarTituloPG(@RequestJsonBody(param = "idElemento") Long idElemento,
            @RequestJsonBody(param = "titulo") String titulo, @RequestJsonBody(param = "tituloCas") String tituloCas) {
        ElementosArbol elem = new ElementosArbol();
        elem.setNombreA(titulo);
        elem.setIdElementoA(idElemento);
        elem.setNombrecasA(tituloCas);
        this.elementoArbolService.guardarTituloPG(elem);
        ElementosArbolController.logger.info("[PUT] : Titulo guardado correctamente");
        return "OK";
    }

    /**
     * Guardar la accion del elemento
     * 
     * @param idElemento
     *            Long id del elemento
     * @param receptores
     *            Integer receptores
     * @param receptoresH
     *            Long receptoresH
     * @param receptoresM
     *            Long receptoresM
     * @param responsable
     *            String responsable
     * @param fechaPrev
     *            String fechaPrev
     * @param tipoReceptor
     *            Long tipoReceptor
     * @param razonAplaz
     *            String razonAplaz
     * @param motivoCancel
     *            String motivoCancel
     * @param descripcion
     *            String descripcion
     * @param nuevafechaprev
     *            String nuevafechaprev
     * @param situacion
     *            Integer situacion
     * @param idPadre
     *            Integer idPadre
     * @param descripcionCas
     *            String descripcionCas
     * @param razonAplazCas
     *            String razonAplazCas
     * @param motivoCancelCas
     *            String motivoCancelCas
     * @param observaciones
     *            String observaciones
     * @param observacionesCas
     *            String observacionesCas
     * @param nombreAccCas
     *            String nombreAccCas
     * @param nombreAcc
     *            String nombreAcc
     * @param preguntaHecha
     *            Long preguntaHecha
     * @return String string
     * @throws ParseException
     *             e e
     */
    @RequestMapping(value = { "/guardarAcciones" }, method = RequestMethod.POST)
    public @ResponseBody String guardarAcciones(@RequestJsonBody(param = "idElemento") Integer idElemento,
            @RequestJsonBody(param = "receptores") Integer receptores,
            @RequestJsonBody(param = "receptoresH") Long receptoresH,
            @RequestJsonBody(param = "receptoresM") Long receptoresM,
            @RequestJsonBody(param = "responsable") String responsable,
            @RequestJsonBody(param = "fechaPrev") String fechaPrev,
            @RequestJsonBody(param = "tipoReceptor") Long tipoReceptor,
            @RequestJsonBody(param = "razonAplaz") String razonAplaz,
            @RequestJsonBody(param = "razonAplazCas") String razonAplazCas,
            @RequestJsonBody(param = "motivoCancel") String motivoCancel,
            @RequestJsonBody(param = "motivoCancelCas") String motivoCancelCas,
            @RequestJsonBody(param = "descripcion") String descripcion,
            @RequestJsonBody(param = "descripcionCas") String descripcionCas,
            @RequestJsonBody(param = "nuevafechaprev") String nuevafechaprev,
            @RequestJsonBody(param = "situacion") Integer situacion,
            @RequestJsonBody(param = "idPadre") Integer idPadre,
            @RequestJsonBody(param = "observaciones") String observaciones,
            @RequestJsonBody(param = "observacionesCas") String observacionesCas,
            @RequestJsonBody(param = "nombreAcc") String nombreAcc,
            @RequestJsonBody(param = "nombreAccCas") String nombreAccCas,
            @RequestJsonBody(param = "preguntaHecha") Long preguntaHecha) throws ParseException {
        Locale locale = LocaleContextHolder.getLocale();
        SimpleDateFormat formatter;
        if (locale.equals(Constantes.LOCALE_ES)) {
            formatter = new SimpleDateFormat(Constantes.ES_DATE_MASK);
        } else {
            formatter = new SimpleDateFormat(Constantes.EU_DATE_MASK);
        }

        Date nuevaFechaPrevDate = null;
        Date fechaPrevDate = null;

        if (nuevafechaprev != null && nuevafechaprev.trim().length() > 0) {
            nuevaFechaPrevDate = formatter.parse(nuevafechaprev);
        }
        if (fechaPrev != null && fechaPrev.trim().length() > 0) {
            fechaPrevDate = formatter.parse(fechaPrev);
        }

        AccionesPg elem = new AccionesPg();
        elem.setCodaccionpg(idElemento);
        elem.setCodelempg(idPadre);
        elem.setNumreceptores(receptores);
        elem.setNumreceph(receptoresH);
        elem.setNumrecepm(receptoresM);
        elem.setCodsituacionfinal(situacion);
        elem.setOrden((long) 0);
        elem.setNombre(nombreAcc);
        elem.setNombrecas(nombreAccCas);
        elem.setNuevafechaprev(nuevaFechaPrevDate);
        elem.setIdaccion((Integer) 0);
        elem.setResponsable(responsable);
        elem.setFechaprev(fechaPrevDate);
        elem.setCodtiporeceptor(tipoReceptor);
        elem.setRazonAplaza(razonAplaz);
        elem.setMotivoCancela(motivoCancel);
        elem.setDescripcion(descripcion);
        elem.setDescripcioncas(descripcionCas);
        elem.setMotivoCancelacas(motivoCancelCas);
        elem.setRazonAplazacas(razonAplazCas);
        elem.setObservaciones(observaciones);
        elem.setObservacionescas(observacionesCas);
        elem.setElemBase(0l);
        elem.setPreguntaHecha(preguntaHecha);

        this.accionesPgService.guardarAcciones(elem);

        ElementosArbolController.logger.info("[guardarAcciones] : accion guardada correctamente");
        return "OK";
    }

    /**
     * Anade una accion nueva
     * 
     * @param elementoId
     *            Integer elementoId
     * @param accionesSel
     *            String accionesSel
     * @param nombre
     *            String nombre
     * @param nombreCas
     *            String nombre cas
     * @param padrepadre
     *            Integer padre del padre del elemento
     * @param usuario
     *            String usuario
     * @param tipoPlan
     *            String tipo de plan
     * @param modo
     *            String si es accion nueva o de la tabla acciones
     * @param model
     *            Model model
     * @return String String
     */
    @RequestMapping(value = { "/anyadirAccionSel" }, method = RequestMethod.POST)
    public String anyadirAccionSel(@RequestJsonBody(param = "elementoId") Integer elementoId,
            @RequestJsonBody(param = "accionesSel") String accionesSel,
            @RequestJsonBody(param = "nombre") String nombre, @RequestJsonBody(param = "nombreCas") String nombreCas,
            Model model, @RequestJsonBody(param = "padrepadre") Integer padrepadre,
            @RequestJsonBody(param = "usuario") String usuario, @RequestJsonBody(param = "tipoPlan") String tipoPlan,
            @RequestJsonBody(param = "modo") String modo) {

        List<AccionesPg> listaAccionesNuevas = new ArrayList<AccionesPg>();
        AccionesPg accion = null;

        // si es una nueva accion creada, no seleccionada
        if (Constantes.TIPO_ACCION_CREADA.equals(accionesSel)) {
            accion = new AccionesPg();
            accion.setCodelempg(elementoId);
            accion.setNombre(nombre);
            accion.setNombrecas(nombreCas);
            listaAccionesNuevas.add(accion);
        } else {

            for (String idAccion : accionesSel.split(Constantes.SEPARADOR_COMA)) {
                accion = new AccionesPg();
                accion.setCodaccionpg(Integer.parseInt(idAccion));
                accion.setCodelempg(elementoId);
                listaAccionesNuevas.add(accion);
            }
        }
        listaAccionesNuevas = this.elementoArbolService.insertarNuevasAcciones(listaAccionesNuevas, modo);

        Map<String, List<AccionesPg>> mapaAcciones = new HashMap<String, List<AccionesPg>>();
        mapaAcciones.put(elementoId.toString(), listaAccionesNuevas);

        ElementosArbolController.logger.info("[PUT] : acciones guardadas correctamente");

        model.addAttribute("acciones", mapaAcciones);
        model.addAttribute("elementoId", elementoId);
        model.addAttribute("elementoPadre", padrepadre);
        model.addAttribute("usuario", usuario);
        model.addAttribute("consulta", 0);
        model.addAttribute("tipoPlan", tipoPlan);
        return "accionNueva";
    }

    /**
     * Guardar el arbol
     * 
     * @param elementos2
     *            String elementos
     * @param indice
     *            Long indice
     * @param nivel
     *            Long nivel
     * @param porcent
     *            Long porcentaje
     * @param fechaAcept
     *            Date fecha aceptacion
     * @param planid
     *            Integer plan id
     * @param nombre
     *            String nombre
     * @param nombreEu
     *            String nombre euskera
     * @param version
     *            Integer version
     * @param anyofin
     *            Long año de fin
     * @param anyoinicio
     *            long año de inicio
     * @return String string
     */
    @RequestMapping(value = { "/guardarArbol" }, method = RequestMethod.POST)
    public @ResponseBody String guardarArbol(@RequestJsonBody(param = "elementos") String elementos2,
            @RequestJsonBody(param = "indice") Long indice, @RequestJsonBody(param = "nivel") Long nivel,
            @RequestParam(value = "fechaAcept", required = false) Date fechaAcept,
            @RequestJsonBody(param = "porcent") Long porcent, @RequestJsonBody(param = "planid") Integer planid,
            @RequestJsonBody(param = "nombre") String nombre, @RequestJsonBody(param = "nombreEu") String nombreEu,
            @RequestJsonBody(param = "version") Integer version, @RequestJsonBody(param = "anyoinicio") Long anyoinicio,
            @RequestJsonBody(param = "anyofin") Long anyofin) {

        PlanesEstrategicos plan = new PlanesEstrategicos();
        plan.setIndiceObligat(indice == null ? 0 : indice);
        plan.setNivelCumplimientoReqeus(nivel == null ? 0 : nivel);
        plan.setFechaAceptacionPlan(fechaAcept);
        plan.setPorcentajeBiling(porcent == null ? 0 : porcent);
        plan.setNombre(nombre);
        plan.setNombreeus(nombreEu);
        plan.setCodplane(planid);
        plan.setCodVersion(version);
        plan.setAnyoinicio(anyoinicio);
        plan.setAnyofin(anyofin);

        List<ElementosPe> elementos = null;
        try {
            elementos = new ObjectMapper().readValue(elementos2, new TypeReference<List<ElementosPe>>() {
            });

        } catch (Exception e) {
            ElementosArbolController.logger.error("guardarArbol:ERROR:", e);
            ElementosArbolController.logger.debug("guardarArbol:ERROR:".concat(e.getMessage()));
            throw new ErrorGenericoException(e.getMessage());
        }

        this.planesEstrategicosService.guardarPlanCompleto(plan, elementos);
        ElementosArbolController.logger.info("[PUT] : Datos arbol guardados correctamente");
        return "OK";
    }

    /**
     * Guardar el helburu del elemento
     * 
     * @param tipoPlan
     *            String tipoPlan
     * @param usuario
     *            String usuario
     * @param titulo
     *            String titulo
     * @param tituloCas
     *            String titulo castellano
     * @param codPlane
     *            Long cod plan
     * @param elementoPadre
     *            Long elemento padre id
     * @param helburu
     *            String helburu
     * @param version
     *            Long version
     * @param helburuCas
     *            String helburu castellano
     * @param model
     *            Model model
     * @param tieneSiNo
     *            Long tieneSiNo
     * @param tieneEus
     *            Long tieneEus
     * @param tieneElebi
     *            Long tieneElebi
     * @param tieneValor
     *            Long tieneValor
     * 
     * @return String String
     */
    @RequestMapping(value = { "/elementoNuevo" }, method = RequestMethod.POST)
    public String elementoNuevo(@RequestJsonBody(param = "tipoPlan") String tipoPlan,
            @RequestJsonBody(param = "usuario") String usuario, @RequestJsonBody(param = "titulo") String titulo,
            @RequestJsonBody(param = "tituloCas") String tituloCas,
            @RequestJsonBody(param = "codPlane") Integer codPlane,
            @RequestJsonBody(param = "elementoPadre") Long elementoPadre,
            @RequestJsonBody(param = "version") Integer version, // @RequestJsonBody(param
                                                                 // =
                                                                 // "helburu")
                                                                 // String
                                                                 // helburu,
            // @RequestJsonBody(param = "helburuCas") String helburuCas,
            @RequestJsonBody(param = "tieneSiNo") Long tieneSiNo, @RequestJsonBody(param = "tieneEus") Long tieneEus,
            @RequestJsonBody(param = "tieneElebi") Long tieneElebi,
            @RequestJsonBody(param = "tieneValor") Long tieneValor, Model model) {

        ElementosPe elem = new ElementosPe();
        elem.setNombreA(titulo);
        elem.setNombrecasA(tituloCas);
        elem.setCodPlaneA((long) codPlane);
        elem.setElementoPadreA(elementoPadre);
        // elem.setHelburuA(helburu);
        // elem.setHelburucasA(helburuCas);
        elem.setVersion((long) version);
        elem.setTieneSiNo(tieneSiNo);
        elem.setTieneEus(tieneEus);
        elem.setTieneElebi(tieneElebi);
        elem.setTieneValor(tieneValor);
        elem.setNivelA(Constantes.ELEMENTO_NIVEL_3);

        ElementosArbol lista = this.elementoArbolService.elementoNuevo(elem);

        List<ElementosArbol> listanivel = new ArrayList<ElementosArbol>();
        listanivel.add(lista);

        model.addAttribute("usuario", usuario);
        model.addAttribute("tipoPlan", tipoPlan);
        model.addAttribute("listaElementos", listanivel);
        model.addAttribute("consulta", 0);
        ElementosArbolController.logger.info("[PUT] : Elemento creado correctamente");
        return "elementosArbolNuevo";
    }

    /**
     * Guardar el helburu del elemento
     * 
     * @param tipoPlan
     *            String tipoPlan
     * @param idPadre
     *            Integer idpadre
     * @param usuario
     *            String usuario
     * @param titulo
     *            String titulo
     * @param codPlane
     *            long codPlane
     * @param tituloCas
     *            String titulo castellano
     * @param nombreaccion
     *            String accion
     * @param nombreaccionCas
     *            String accion castellano
     * @param model
     *            Model model
     * 
     * @return String String
     */
    @RequestMapping(value = { "/nuevoElemNivel4" }, method = RequestMethod.POST)
    public String nuevoElemNivel4(@RequestJsonBody(param = "idPadre") Long idPadre,
            @RequestJsonBody(param = "codPlane") Long codPlane, @RequestJsonBody(param = "tipoPlan") String tipoPlan,
            @RequestJsonBody(param = "usuario") String usuario, @RequestJsonBody(param = "titulo") String titulo,
            @RequestJsonBody(param = "tituloCas") String tituloCas,
            @RequestJsonBody(param = "nombreaccion") String nombreaccion,
            @RequestJsonBody(param = "nombreaccionCas") String nombreaccionCas, Model model) {
        AccionesPg accion = new AccionesPg();
        accion.setNombre(nombreaccion);
        accion.setNombrecas(nombreaccionCas);
        ElementosArbol elem = new ElementosArbol();
        elem.setNombreA(titulo);
        elem.setNombrecasA(tituloCas);
        elem.setElementoPadreA(idPadre);
        elem.setCodPlaneA(codPlane);
        elem.setNivelA(Constantes.ELEMENTO_NIVEL_4);

        ElementosArbol lista = this.elementoArbolService.elementoNuevoNivel4(elem, accion);

        List<ElementosArbol> listanivel = new ArrayList<ElementosArbol>();
        listanivel.add(lista);
        Map<String, List<AccionesPg>> mapaAcciones = new HashMap<String, List<AccionesPg>>();
        mapaAcciones.put(lista.getHijosArbol().get(0).getIdElementoA().toString(),
                lista.getHijosArbol().get(0).getAcciones());

        model.addAttribute("usuario", usuario);
        model.addAttribute("tipoPlan", tipoPlan);
        model.addAttribute("listaElementos", listanivel);
        model.addAttribute("consulta", 0);
        model.addAttribute("acciones", mapaAcciones);
        ElementosArbolController.logger.info("[PUT] : Elemento nivel 4 creado correctamente");
        return "elementosArbolNuevo4";
    }

    /**
     * Guardar el helburu del elemento
     * 
     * @param titulo
     *            String titulo del elemento
     * @param tituloCas
     *            String titulo del elemento castellano
     * @param codPlane
     *            Long codigo de planificacion
     * @param elementoId
     *            Long id del elemento
     * @param helburu
     *            String helburu
     * @param helburuCas
     *            String helburu castellano
     * @param codVersion
     *            Long codigo version
     * @param model
     *            Model model
     * 
     * @return String String
     */
    @RequestMapping(value = { "/modificarElemento" }, method = RequestMethod.POST)
    public @ResponseBody String modificarElemento(@RequestJsonBody(param = "titulo") String titulo,
            @RequestJsonBody(param = "tituloCas") String tituloCas, @RequestJsonBody(param = "version") Long codVersion,
            @RequestJsonBody(param = "codPlane") Long codPlane, @RequestJsonBody(param = "elementoId") Long elementoId,
            @RequestJsonBody(param = "helburu") String helburu,
            @RequestJsonBody(param = "helburuCas") String helburuCas, Model model) {
        ElementosArbol elem = new ElementosArbol();
        elem.setNombreA(titulo);
        elem.setNombrecasA(tituloCas);
        elem.setCodPlaneA(codPlane);
        elem.setVersion(codVersion);
        elem.setIdElementoA(elementoId);
        elem.setHelburuA(helburu);
        elem.setHelburucasA(helburuCas);
        this.elementoArbolService.modificarElemento(elem);
        ElementosArbolController.logger.info("[PUT] : Elemento modificado correctamente");
        return "OK";
    }

    /**
     * Borra un elemento
     * 
     * @param elementoId
     *            Long id del elemento
     * @param codPlane
     *            Long codplane
     * @param codVersion
     *            Long codVersion
     * @return String string
     */
    @RequestMapping(value = { "/borrarElemento" }, method = RequestMethod.GET)
    public @ResponseBody String borrarElemento(@RequestParam(value = "elementoId", required = false) Long elementoId,
            @RequestParam(value = "planid", required = false) Long codPlane,
            @RequestParam(value = "version", required = false) Long codVersion) {

        PlanesEstrategicos planes = new PlanesEstrategicos();
        if (codPlane != null && codVersion != null) {
            planes.setCodplane(codPlane.intValue());
            planes.setCodVersion(codVersion.intValue());
        }
        this.elementoArbolService.borrarElemento(elementoId, planes);

        ElementosArbolController.logger.info("[DELETE] : Elemento borrado correctamente");
        return "OK";
    }

    /**
     * Borra una accion
     * 
     * @param accion
     *            Integer id accion
     * @param elementoId
     *            Integer id del elemento
     * 
     * @return String string
     */
    @RequestMapping(value = { "/borrarAccion" }, method = RequestMethod.GET)
    public @ResponseBody String borrarAccion(@RequestParam(value = "elementoid", required = false) Integer elementoId,
            @RequestParam(value = "accion", required = false) Integer accion) {
        AccionesPg accionpg = new AccionesPg();
        accionpg.setCodaccionpg(accion);
        accionpg.setCodelempg(elementoId);

        this.accionesPgService.remove(accionpg);

        ElementosArbolController.logger.info("[DELETE] : Accion borrada correctamente");
        return "OK";
    }

    /**
     * Borra una accion
     * 
     * @param accion
     *            Integer id accion
     * @param elementoId
     *            Integer id del elemento
     * 
     * @return String string
     */
    @RequestMapping(value = { "/borrarElem4YAcciones" }, method = RequestMethod.GET)
    public @ResponseBody String borrarElem4YAcciones(
            @RequestParam(value = "elementoid", required = false) Integer elementoId) {
        ElementosPg elem = new ElementosPg();
        elem.setCodelempg(elementoId);
        this.elementosPgService.remove(elem);
        ElementosArbolController.logger.info("[DELETE] : elemento nivel 4 borrado correctamente");
        return "OK";
    }

    /**
     * Guardar el helburu del elemento
     * 
     * @param oharrak
     *            String oharrak del elemento
     * @param codPlane
     *            Long codigo de planificacion
     * @param elementoId
     *            Long id del elemento
     * 
     * @return String String
     */
    @RequestMapping(value = { "/editarOharrak" }, method = RequestMethod.GET)
    public String editarOharrak(@RequestParam(value = "oharrak", required = false) String oharrak,
            @RequestParam(value = "codPlane", required = false) Long codPlane,
            @RequestParam(value = "elementoId", required = false) Long elementoId) {
        ElementosPe elem = new ElementosPe();
        elem.setOharrak(oharrak);
        elem.setCodPlaneA(codPlane);
        elem.setIdElementoA(elementoId);
        this.elementoArbolService.editarOharrak(elem);
        ElementosArbolController.logger.info("[PUT] : Oharrak actualizado correctamente");
        return "OK";
    }

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

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

    /**
     * Operacion CRUD Delete. Borrado del registro correspondiente al identificador especificado.
     *
     * @param idElemento
     *            Long Identificador del objeto que se desea eliminar.
     * @return Elemento Bean eliminado.
     */
    @RequestMapping(value = "/{idElemento}", method = RequestMethod.DELETE)
    @ResponseStatus(value = HttpStatus.OK)
    public @ResponseBody Elemento remove(@PathVariable Long idElemento) {
        Elemento elemento = new Elemento();
        elemento.setIdElemento(idElemento);
        this.elementoService.remove(elemento);
        ElementosArbolController.logger.info("[DELETE] : Elemento borrado correctamente");
        return elemento;
    }

    /*
     * METODOS COMPONENTE RUP_TABLE
     * 
     */

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

        return "elementosArbol";
    }

    /**
     * Operacion de filtrado del componente RUP_TABLE.
     * 
     * @param filterElemento
     *            Elemento 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<Elemento> Dto que contiene el resultado del filtrado realizado por
     *         el componente RUP_TABLE.
     */
    @RequestMapping(value = "/filter", method = RequestMethod.POST)
    public @ResponseBody JQGridResponseDto<Elemento> filter(@RequestJsonBody(param = "filter") Elemento filterElemento,
            @RequestJsonBody JQGridRequestDto jqGridRequestDto) {
        ElementosArbolController.logger.info("[POST - filter] : Obtener Elementos");
        return this.elementoService.filter(filterElemento, jqGridRequestDto, false);
    }

    /**
     * Borrado multiple de registros
     * 
     * @param filterElemento
     *            Elemento 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") Elemento filterElemento,
            @RequestJsonBody JQGridRequestDto jqGridRequestDto) {
        ElementosArbolController.logger
                .info("[POST - search] : [POST - removeMultiple] : Eliminar multiples Elementos");
        this.elementoService.removeMultiple(filterElemento, jqGridRequestDto, false);
        ElementosArbolController.logger.info("All entities correctly deleted!");

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

    /**
     * Crear excel planes
     * 
     * @param tipo
     *            String tipo plan
     * @param version
     *            Integer version
     * @param codPlane
     *            Integer codigo de plan
     * @param request
     *            HttpServletRequest request
     * @param response
     *            HttpServletResponse response
     * @return String string
     * @throws IOException
     *             e e
     * @throws FileNotFoundException
     *             e e
     */
    @RequestMapping(value = { "/crearExcel" }, method = RequestMethod.GET)
    public @ResponseBody() void crearExcel(HttpServletRequest request, HttpServletResponse response,
            @RequestParam(value = "version", required = false) Integer version,
            @RequestParam(value = "codPlane", required = false) Integer codPlane,
            @RequestParam(value = "tipo", required = false) String tipo) throws FileNotFoundException, IOException {

        List<ElementosArbol> lista = null;
        if (tipo.equals(Constantes.TIPO_PLAN_ESTRAT)) {
            PlanesEstrategicos planid = new PlanesEstrategicos();
            planid.setCodplane(codPlane);
            planid.setCodVersion(version);
            PlanesEstrategicos plan = this.planesEstrategicosService.find(planid);
            lista = this.elementoArbolService.findAll(codPlane, version, null);
            this.excelService.generarExcelPE(this.appMessageSource, plan, lista, response);
        } else {
            PlanesGestion planid = new PlanesGestion();
            planid.setCodplang(codPlane);
            PlanesGestion plan = this.planesGestionService.find(planid);
            Map<String, List<AccionesPg>> acciones = this.accionesPgService.buscarAccionesPgArbol(codPlane);
            lista = this.elementoArbolService.findAllGestion(codPlane, null);
            this.excelService.generarExcelPG(this.appMessageSource, acciones, lista, plan, response);
        }

        ElementosArbolController.logger.info("[PUT] : excel correctamente");

    }

    /**
     * Crear pdf planes
     * 
     * @param tipo
     *            String tipo plan
     * @param version
     *            Integer version
     * @param codPlane
     *            Integer codigo de plan
     * @param request
     *            HttpServletRequest request
     * @param response
     *            HttpServletResponse response
     * @return String string
     * @throws IOException
     *             e e
     */
    @RequestMapping(value = { "/crearPdf" }, method = RequestMethod.GET)
    public @ResponseBody() void crearPdf(HttpServletRequest request, HttpServletResponse response,
            @RequestParam(value = "version", required = false) Integer version,
            @RequestParam(value = "codPlane", required = false) Integer codPlane,
            @RequestParam(value = "tipo", required = false) String tipo) throws IOException {

        List<ElementosArbol> lista = null;
        ByteArrayOutputStream baos;
        PlanesEstrategicos planid = new PlanesEstrategicos();
        planid.setCodplane(codPlane);
        planid.setCodVersion(version);
        PlanesEstrategicos plan = this.planesEstrategicosService.find(planid);
        lista = this.elementoArbolService.findAll(codPlane, version, null);
        baos = this.pdfService.generarPdfPE(this.appMessageSource, plan, lista);
        try {
            InputStream is = new ByteArrayInputStream(baos.toByteArray());
            Utilities.downloadDocument(response, Constantes.NOMBRE_PDF
                    .concat(UtilDate.formateaFechaDDMMYYYY(UtilDate.currentDate())).concat(Constantes.EXTENSION_PDF),
                    is, "application/pdf");

        } catch (IOException e) {
            ElementosArbolController.logger.error("IOException", e);
        }

        ElementosArbolController.logger.info("[PUT] : pdf correctamente");

    }

}
