package com.ejie.aa20b.control;

import java.io.IOException;
import com.ejie.aa20b.service.PlanosService;
import com.ejie.aa20b.util.Aa20bConstantes;
import com.ejie.x38.dto.JQGridJSONModel;
import com.ejie.x38.dto.Jerarquia;
import com.ejie.x38.dto.Pagination;
import com.ejie.x38.util.ObjectConversionManager;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
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.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.ServletRequestDataBinder;
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 org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.support.ByteArrayMultipartFileEditor;
import com.ejie.x38.util.DateTimeManager;
import com.ejie.aa20b.model.Planos;
import com.bea.core.repackaged.springframework.beans.propertyeditors.CustomDateEditor;
import com.bea.core.repackaged.springframework.context.i18n.LocaleContextHolder;
import java.util.Date;

/**
 * PlanosController generated by UDA, 12-ene-2015 16:12:03.
 * 
 * @author UDA
 */

@Controller
@RequestMapping(value = "/planos")
public class PlanosController {

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

	@Autowired
	private PlanosService planosService;

	@InitBinder
	protected void initBinder(HttpServletRequest request,
			ServletRequestDataBinder binder) throws ServletException {
		binder.registerCustomEditor(byte[].class,
				new ByteArrayMultipartFileEditor());
		binder.registerCustomEditor(
				Date.class,
				new CustomDateEditor(DateTimeManager
						.getDateTimeFormat(LocaleContextHolder.getLocale()),
						true));
	}

	/**
	 * Method 'getCreateForm'.
	 * 
	 * @param model
	 *            Model
	 * @param request
	 *            HttpServletRequest
	 * @return String
	 */
	@RequestMapping(value = "maint", method = RequestMethod.GET)
	public String getCreateForm(Model model, HttpServletRequest request) {
		PlanosController.logger.info("[GET - View] : planos");
		// Borrar el filtro de la sesion
		request.getSession().removeAttribute("FiltroPlanos");
		return "planos";
	}

	/**
	 * Method 'maintVolver'.
	 * 
	 * @param model
	 *            Model
	 * @param request
	 *            HttpServletRequest
	 * @return String
	 */
	@RequestMapping(value = "maintVolver", method = RequestMethod.GET)
	public String maintVolver(Model model, HttpServletRequest request) {
		PlanosController.logger.info("[GET - View] : planos");
		// Meter en sesion el filtro para si edita un parte al volver cargar el
		// filtro
		Planos planoFiltro = (Planos) request.getSession().getAttribute(
				"FiltroPlanos");

		model.addAttribute("FiltroPlano", planoFiltro);

		return "planos";
	}

	/**
	 * Method 'getById'.
	 * 
	 * @param idplano
	 *            Long
	 * @return planos Planos
	 */
	@RequestMapping(value = "/{idplano}", method = RequestMethod.GET)
	public @ResponseBody
	Planos getById(@PathVariable Long idplano) {
		Planos planos = new Planos();
		planos.setIdplano(idplano);
		planos = this.planosService.find(planos);
		PlanosController.logger
				.info("[GET - findBy_PK] : Obtener Planos por PK");
		return planos;
	}

	@RequestMapping(value = "/cargarPlano", method = RequestMethod.GET)
	public void cargarPlano(HttpServletRequest req, HttpServletResponse res,
			Locale locale) throws IOException {

		// init
		byte[] dibujo = null;
		String idioma = locale.getLanguage();
		ServletOutputStream out = res.getOutputStream();
		Planos plano = new Planos();

		// set
		res.setContentType("image/jpeg");

		String planoSel = req.getParameter("idPlano");
		Long idPlano = Long.parseLong(planoSel);
		plano.setIdplano(idPlano);
		PlanosController.logger
				.info("[GET - findBy_PK] : Mostrar Plano + idPlano : "
						+ idPlano);

		// execute
		dibujo = this.planosService.buscaDibujo(plano, idioma);

		// blob treatment
		int nBytes = 0;
		if (dibujo != null) {
			nBytes = dibujo.length;
			PlanosController.logger
					.info("[GET - BUSCA Plano] : Tamaño Plano : "
							+ dibujo.length);
			while (nBytes > 0) {
				out.write(dibujo, 0, nBytes);
				nBytes = dibujo.length - nBytes;
			}
		}

		// end
		out.flush();
		out.close();
	}

	@RequestMapping(value = "/mostrarPlano", method = RequestMethod.GET)
	public void mostrarPlano(HttpServletRequest req, HttpServletResponse res,
			Locale locale, Model model) throws IOException {

		// init
		byte[] dibujo = null;
		String idioma = locale.getLanguage();
		ServletOutputStream out = res.getOutputStream();
		Planos plano = new Planos();
		PlanosController.logger.info("[GET - BUSCA Plano] : El idioma es : "
				+ idioma);
		// get
		String edificio = req.getParameter("edificio");
		Integer planta = 0;
		Integer zona = 0;

		if (req.getParameter("planta") != null) {
			planta = Integer.parseInt(req.getParameter("planta"));
		}
		if (req.getParameter("zona") != null) {
			zona = Integer.parseInt(req.getParameter("zona"));
		}

		PlanosController.logger
				.info("[GET - findBy_PK] : Mostrar Plano + edificio : "
						+ edificio + " planta: " + planta + " zona: " + zona);
		// set
		res.setContentType("image/jpeg");

		plano.setIdedificio(edificio);
		plano.setIdplanta(planta);
		plano.setIdzona(zona);

		// execute
		dibujo = this.planosService.buscaDibujo(plano, idioma);

		// blob treatment
		int nBytes = 0;
		if (dibujo != null) {
			nBytes = dibujo.length;
			PlanosController.logger
					.info("[GET - BUSCA Plano] : Tamaño Plano : "
							+ dibujo.length);
			while (nBytes > 0) {
				out.write(dibujo, 0, nBytes);
				nBytes = dibujo.length - nBytes;
			}
		}

		// end
		out.flush();
		out.close();
	}

	/**
	 * Method 'getAll'.
	 * 
	 * @param filterPlanos
	 *            Planos
	 * @return List
	 */
	@RequestMapping(method = RequestMethod.GET)
	public @ResponseBody
	List<Planos> getAll(@ModelAttribute Planos filterPlanos) {
		PlanosController.logger
				.info("[GET - find_ALL] : Obtener Planos por filtro");
		return this.planosService.findAll(filterPlanos, null);
	}

	/**
	 * Method 'obtenerListaPlanos'.
	 * 
	 * @param filterPlanos
	 *            Planos
	 * @return List
	 */
	@RequestMapping(value = "obtenerListaPlanos", method = RequestMethod.GET)
	public @ResponseBody
	List<Planos> obtenerListaPlanos(String codEdif, Integer codPlanta,
			Integer codZona) {
		PlanosController.logger
				.info("[GET - find_ALL] : Obtener lista de Planos por edificio,zona y planta");

		return this.planosService.obtenerListaPlanos(codEdif, codPlanta,
				codZona);
	}

	/**
	 * Method 'edit'.
	 * 
	 * @param planos
	 *            Planos
	 * @return Planos
	 */
	@RequestMapping(method = RequestMethod.PUT)
	public @ResponseBody
	Planos edit(@RequestBody Planos planos) {
		Planos planosAux = this.planosService.update(planos);
		PlanosController.logger
				.info("[PUT] : Planos actualizado correctamente");
		return planosAux;
	}

	/**
	 * Method 'add'.
	 * 
	 * @param planos
	 *            Planos
	 * @return Planos
	 */
	@RequestMapping(method = RequestMethod.POST)
	public @ResponseBody
	Planos add(@RequestBody Planos planos) {
		Planos planosAux = this.planosService.add(planos);
		PlanosController.logger.info("[POST] : Planos insertado correctamente");
		return planosAux;
	}

	/**
	 * Method 'remove'.
	 * 
	 * @param idplano
	 *            Long
	 * @return planos
	 */
	@RequestMapping(value = "/{idplano}", method = RequestMethod.DELETE)
	@ResponseStatus(value = HttpStatus.OK)
	public @ResponseBody
	Planos remove(@PathVariable Long idplano) {
		Planos planos = new Planos();
		planos.setIdplano(idplano);
		this.planosService.remove(planos);
		PlanosController.logger.info("[DELETE] : Planos borrado correctamente");
		return planos;
	}

	/**
	 * Method 'removeAll'.
	 * 
	 * @param planosIds
	 *            List
	 * @return planosList
	 */
	@RequestMapping(value = "/deleteAll", method = RequestMethod.POST)
	@ResponseStatus(value = HttpStatus.OK)
	public @ResponseBody
	List<List<String>> removeMultiple(@RequestBody List<List<String>> planosIds) {
		List<Planos> planosList = new ArrayList<Planos>();
		for (List<String> planosId : planosIds) {
			Iterator<String> iterator = planosId.iterator();
			Planos planos = new Planos(); // NOPMD - Objeto nuevo en la lista
											// (parametro del servicio)
			planos.setIdplano(ObjectConversionManager.convert(iterator.next(),
					Long.class));
			planosList.add(planos);
		}
		this.planosService.removeMultiple(planosList);
		PlanosController.logger
				.info("[POST - DELETE_ALL] : Planos borrados correctamente");
		return planosIds;
	}

	/**
	 * Method 'getAllJQGrid'.
	 * 
	 * @param filterPlanos
	 *            Planos
	 * @param pagination
	 *            Pagination
	 * @param request
	 *            HttpServletRequest
	 * @return JQGridJSONModel
	 */
	@RequestMapping(method = RequestMethod.GET, headers = { "JQGridModel=true" })
	public @ResponseBody
	JQGridJSONModel getAllJQGrid(@ModelAttribute Planos filterPlanos,
			@ModelAttribute Pagination pagination, HttpServletRequest request) {

		/*
		 * List<Planos> planoss = this.planosService.obtenerPlanos(filterPlanos,
		 * pagination, false); Long recordNum =
		 * this.planosService.obtenerPlanosCount(filterPlanos, false);
		 */
		List<Jerarquia<Planos>> planoss = this.planosService
				.obtenerPlanosJerarquia(filterPlanos, pagination, false);
		Long recordNum = this.planosService.obtenerPlanosJerarquiaCount(
				filterPlanos, false, pagination);

		PlanosController.logger.info("[GET - jqGrid] : Obtener Planos");
		// Meter en sesion el filtro para si edita un parte al volver cargar el
		// filtro

		request.getSession().setAttribute("FiltroPlanos", filterPlanos);

		return new JQGridJSONModel(pagination, recordNum, planoss);
	}

	@RequestMapping(method = RequestMethod.GET, headers = { "JQGridModel_selected=true" })
	public @ResponseBody
	TreeMap<String, TreeMap<String, String>> getAllJQGridSelected(
			@ModelAttribute Planos filterPlanosJerarquia,
			@ModelAttribute Pagination pagination) {
		return this.planosService.obtenerPlanosSelect(filterPlanosJerarquia,
				pagination);
	}

	/**
	 * Method 'getById'.
	 * 
	 * @param idPlanoBusc
	 *            Long
	 * @return editarPlano String
	 */
	@RequestMapping(value = "/buscarPlano", method = RequestMethod.POST)
	public String getById(@RequestParam Long idPlanoBusc, Model model) {

		PlanosController.logger.info("[GET - findBy_PK] : Plano");

		Planos plano = new Planos();

		plano.setIdplano(idPlanoBusc);
		plano = this.planosService.obtenerPlano(plano);

		PlanosController.logger.info("[GET - findBy_PK] : Edificio: "
				+ plano.toString());

		model.addAttribute("Plano", plano);
		model.addAttribute("accion", Aa20bConstantes.ACCION_MODIFICAR);

		return "editarPlano";
	}

	/**
	 * Method 'nuevoPlano'.
	 * 
	 * @param model
	 *            Model
	 * @return String
	 */
	@RequestMapping(value = "/nuevoPlano", method = RequestMethod.GET)
	public String nuevoPlano(Model model) {

		PlanosController.logger.info("[GET - View] : nuevo plano");
		return "nuevoPlano";
	}

	private Map<String, Object> getFileReturnMap(MultipartFile file) {
		Map<String, Object> mapaRetorno = new HashMap<String, Object>();
		// mapaRetorno.put("url",
		// "../upload?fileName=" + file.getOriginalFilename());
		mapaRetorno.put("name", file.getOriginalFilename());
		mapaRetorno.put("type", file.getContentType());
		mapaRetorno.put("size", file.getSize());
		// mapaRetorno.put("delete_url",
		// "../upload?fileName=" + file.getOriginalFilename());
		// mapaRetorno.put("delete_type", "DELETE");
		return mapaRetorno;
	}

	@RequestMapping(value = "insertarPlano", method = RequestMethod.POST)
	public @ResponseBody
	List<Map<String, Object>> insertarPlano(
			@RequestParam(value = "ficheroPlano", required = false) MultipartFile ficheroPlano,
			@RequestParam(value = "idplano", required = true) Long idplano,
			@ModelAttribute Planos plano) throws IOException {
		PlanosController.logger.info("[POST] : Entramos en insertar plano");

		List<Map<String, Object>> filesMetaInfo = new ArrayList<Map<String, Object>>();

		if (ficheroPlano != null) {
			if (ficheroPlano.getSize() > 0) {

				byte[] ficheroBytes = ficheroPlano.getBytes();

				plano.setPlanoDibujo(ficheroBytes);

				this.planosService.modificaDibujoPlano(plano);
				filesMetaInfo.add(this.getFileReturnMap(ficheroPlano));
			}

		}
		PlanosController.logger.info("[POST] : Plano insertado correctamente");
		return filesMetaInfo;

	}

	@RequestMapping(value = "nuevoPlano", method = RequestMethod.POST)
	public @ResponseBody
	List<Map<String, Object>> nuevoPlano(
			@RequestParam(value = "ficheroPlano", required = false) MultipartFile ficheroPlano,
			@RequestParam(value = "idEdificio", required = true) String idEdificio,
			@RequestParam(value = "idZona", required = true) Integer idZona,
			@RequestParam(value = "idPlanta", required = true) Integer idPlanta,
			@ModelAttribute Planos plano) throws IOException {
		PlanosController.logger.info("[POST] : Entramos en nuevo plano");

		List<Map<String, Object>> filesMetaInfo = new ArrayList<Map<String, Object>>();

		plano.setIdedificio(idEdificio);
		plano.setIdzona(idZona);
		plano.setIdplanta(idPlanta);

		if (ficheroPlano != null) {
			if (ficheroPlano.getSize() > 0) {

				byte[] ficheroBytes = ficheroPlano.getBytes();

				plano.setPlanoDibujo(ficheroBytes);

				this.planosService.nuevoPlano(plano);
				filesMetaInfo.add(this.getFileReturnMap(ficheroPlano));
			}

		}
		PlanosController.logger.info("[POST] : Plano insertado correctamente");
		return filesMetaInfo;

	}

	/**
	 * 
	 * Method 'edificioZonaTienePlanos'.
	 * 
	 * 
	 * puestoIntroducido String
	 * 
	 * @return List
	 */

	@RequestMapping(value = "/edificioZonaTienePlanos", method = RequestMethod.POST)
	public @ResponseBody
	Boolean edificioZonaTienePlanos(@RequestParam String codEdificio,
			@RequestParam ArrayList<Integer> zonasSeleccionadas, Model model,
			HttpServletRequest request) {

		Planos plano = new Planos();

		PlanosController.logger
				.info("[POST - edificioZonaTienePlanos] : Comprobando si la zona a desasociar tiene planos asociados: ");

		for (int i = 0; i < zonasSeleccionadas.size(); i++) {
			plano.setIdedificio(codEdificio);
			plano.setIdzona(zonasSeleccionadas.get(i));

			List<Planos> lsPlanos = this.planosService.findAll(plano, null);
			if (lsPlanos.size() > 0) {
				return true;
			}

		}
		return false;
	}

	/**
	 * 
	 * Method 'edificioZonaPlantaTienePlanos'.
	 * 
	 * 
	 * puestoIntroducido String
	 * 
	 * @return List
	 */

	@RequestMapping(value = "/edificioZonaPlantaTienePlanos", method = RequestMethod.POST)
	public @ResponseBody
	Boolean edificioZonaPlantaTienePlanos(@RequestParam String codEdificio,
			@RequestParam Integer codZona,
			@RequestParam ArrayList<Integer> plantasSeleccionadas, Model model,
			HttpServletRequest request) {

		Planos plano = new Planos();

		PlanosController.logger
				.info("[POST - edificioZonaPlantaTienePlanos] : Comprobando si la planta a desasociar tiene planos asociados: ");

		for (int i = 0; i < plantasSeleccionadas.size(); i++) {
			plano.setIdedificio(codEdificio);
			plano.setIdzona(codZona);
			plano.setIdplanta(plantasSeleccionadas.get(i));

			List<Planos> lsPlanos = this.planosService.findAll(plano, null);
			if (lsPlanos.size() > 0) {
				return true;
			}

		}
		return false;
	}

	/**
	 * Method 'asociarPadreHijo'.
	 * 
	 * @param idPlanoPadre
	 *            Long
	 * @param ejeXdesde
	 *            Long
	 * @param ejeYdesde
	 *            Long
	 * @param codEdificio
	 *            String
	 * @param codZona
	 *            Integer
	 * @param codPlanta
	 *            Integer
	 * @return buscarFicha String
	 */
	@RequestMapping(value = "/asociarPadreHijo", method = RequestMethod.POST)
	public @ResponseBody
	Boolean asociarPadreHijo(@RequestParam Long idPlanoPadre,
			@RequestParam Long ejeXdesde, @RequestParam Long ejeYdesde,
			@RequestParam String codEdificio, @RequestParam Integer codZona,
			@RequestParam Integer codPlanta, Model model,
			HttpServletRequest request) {

		Planos plano = new Planos();

		plano.setIdpadre(idPlanoPadre);
		plano.setEjexdesde(ejeXdesde);
		plano.setEjeydesde(ejeYdesde);
		plano.setIdedificio(codEdificio);
		plano.setIdzona(codZona);
		plano.setIdplanta(codPlanta);

		PlanosController.logger.info("[POST - asociarPadreHijo] : ");

		Planos planosAux = this.planosService.asociarPadreHijo(plano);

		if (planosAux != null) {
			return true;
		} else {
			return false;
		}

	}

}
