package com.pas.controller;

import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.validation.Valid;
import javax.ws.rs.core.MediaType;

import org.codehaus.jackson.jaxrs.JacksonJsonProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
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.servlet.ModelAndView;

import com.pas.beans.Constants;
import com.pas.model.ParkingPlace;
import com.pas.model.User;
import com.pas.service.ParkingPlaceService;
import com.pas.service.UserService;
import com.pas.web.PPlaceForm;
import com.pas.web.PPlaceSearchForm;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;

@Controller
@RequestMapping(value = "/parkingPlace")
public class ParkingPlaceController {
	@Autowired
	ParkingPlaceService parkingPlaceService;

	@Autowired
	UserService userService;

	@RequestMapping("/search")
	public String SearchParkingPlacesForm(Map<String, Object> map) {
		map.put("pPlaceSearchForm", new PPlaceSearchForm());
		
		return "seachParkingPlacesForm";
	}

	@RequestMapping("/register")
	public String ResultsParkingPlacesForm(Map<String, Object> map) {
		map.put("pPlaceForm", new PPlaceForm());
		
		return "registerParkingPlace";
	}
	
	@RequestMapping("/searchResults")
	public String ResultsParkingPlacesForm(@ModelAttribute @Valid PPlaceSearchForm pPlaceSearchForm, BindingResult result, Map<String, Object> map) {
		String pageReturn="resultsParkingPlacesForm";
		if ( !result.hasErrors() ) {
			//Se realiza la busqueda por parámetros
			List<ParkingPlace> listPPlaces = parkingPlaceService.getAllParkingPlace();
			double[] latlonAverage= getLatLonAverage(listPPlaces);
			
			map.put("latAverage", latlonAverage[0]);
			map.put("lonAverage", latlonAverage[1]);
			map.put("pPlaceSearchForm", pPlaceSearchForm);
			map.put("pPlaceList", listPPlaces);
		} else {
			map.put("pPlaceSearchForm", pPlaceSearchForm);
			pageReturn="seachParkingPlacesForm";
		}
		return pageReturn;
	}
	
	/**
	 * Crear la plaza de parking segun los valores informados en el formulario de creación
	 * @param PPlaceForm
	 */
	@RequestMapping(value = "/add", method = RequestMethod.POST)
	public String add(@ModelAttribute @Valid PPlaceForm pPlaceForm, BindingResult result, Map<String, Object> map) {
		String pageReturn="userScreen";
		
		if ( !result.hasErrors() ) {
			//Obtener el objeto usuario
			Authentication auth = SecurityContextHolder.getContext().getAuthentication();
			User user = (auth != null ? userService.getUserByUserName(auth.getName()) : null); 
			
			if (user != null) {
				//Crear el objeto de plaza de aparcamiento
				ParkingPlace parkingPlace = new ParkingPlace();
				parkingPlace.setName(pPlaceForm.getName());
				parkingPlace.setCountry(pPlaceForm.getCountry());
				parkingPlace.setAddress(pPlaceForm.getAddress());
				parkingPlace.setCity(pPlaceForm.getCity());
				parkingPlace.setCountry(pPlaceForm.getCountry());
				parkingPlace.setZipCode(pPlaceForm.getZipCode());
				parkingPlace.setDateRegistration(new Date());
				parkingPlace.setUser(user);
				
				//Lanzar el servicio de creación de la plaza de aparcamiento
				parkingPlaceService.add(parkingPlace);
				
			} else {
				map.put("pPlaceForm", pPlaceForm);
				map.put("userError", "No se ha encontrado usuario en BBDD");
				pageReturn="registerParkingPlace";
			}
		} else {
			map.put("pPlaceForm", pPlaceForm);
			pageReturn="registerParkingPlace";
		}
		
		return pageReturn;
	}
	
	/**
	 * Modificar la plaza de parking segun los valores informados en el formulario
	 * @param PPlaceForm
	 */
	@RequestMapping(value = "/edit", method = RequestMethod.POST)
	public void edit(@ModelAttribute PPlaceForm pPlaceForm) {
		//Obtener el objeto usuario
		User user = userService.getUser(pPlaceForm.getId());
		
		//Obtener el objeto de la plaza de aparcamiento a partir de su id
		ParkingPlace parkingPlace = parkingPlaceService.getParkingPlace(pPlaceForm.getId());
		
		//Modificar el usuario con los parámetros informados
		parkingPlace.setAddress(pPlaceForm.getAddress());
		parkingPlace.setCity(pPlaceForm.getCity());
		parkingPlace.setCountry(pPlaceForm.getCountry());
		parkingPlace.setZipCode(pPlaceForm.getZipCode());
		parkingPlace.setDateRegistration(new Date());
		parkingPlace.setUser(user);
		
		//Lanzar el servicio de modificación de la plaza de aparcamiento
		parkingPlaceService.edit(parkingPlace);
	}
	
	/**
	 * Eliminar plaza de aparcamiento
	 * @param parkingPlaceId Identificador de la plaza de aparcamiento
	 */
	@RequestMapping(value = "/delete/{id}", method = RequestMethod.GET)
	public void delete(@PathVariable int parkingPlaceId) {
		if (parkingPlaceId > 0) {
			parkingPlaceService.delete(parkingPlaceId);
		}
	}
	
	/**
	 * Obtener la plaza de aparcamiento a partir de su identificador
	 * @param parkingPlaceId Identificador de la plaza de aparcamiento
	 * @return
	 */
	@RequestMapping(value = "/get/{parkingPlaceId}", method = RequestMethod.GET)
	public String getParkingPlace(@PathVariable int parkingPlaceId, Map<String, Object> map) {
		String pageReturn="detailParkingPlace";
		if (parkingPlaceId > 0) {
			map.put("pplace", parkingPlaceService.getParkingPlace(parkingPlaceId));
		} else {
			map.put("message", "Se ha producido un error en la carga del detelle de la plaza de aparcamiento. Vuelva a intentarlo pasado unos minutos");
			pageReturn= "welcome";
		}
		return pageReturn;
	}
	
	/**
	 * Obtener todos las plaza de aparcamiento
	 * @return
	 */
	@RequestMapping(value = "/getAll", method = RequestMethod.GET)
	public String getAllParkingPlace(Map<String, Object> map) {
		//Obtener el objeto usuario
		Authentication auth = SecurityContextHolder.getContext().getAuthentication();
		User user = (auth != null ? userService.getUserByUserName(auth.getName()) : null); 
		
		if (user != null) {
			map.put("myPLaces", parkingPlaceService.getParkingPlaceByUser(user));
		} else {
			map.put("userError", "No se ha encontrado usuario en BBDD.");
		}
		
		return "userParkingPlaces";
	}

	@RequestMapping(value="/detail/{id}", method = RequestMethod.GET)
	public ModelAndView detailParkingPlace(@PathVariable("id") String id) {

		ModelAndView mav = new ModelAndView();
		ClientConfig clientConfig = new DefaultClientConfig();
		clientConfig.getClasses().add(JacksonJsonProvider.class);
		Client client = Client.create(clientConfig);
		WebResource service = client.resource(Constants.userParkingPlaces_WSURL)
				.path("/detail").path(id);
		
		ClientResponse response = service.type(MediaType.APPLICATION_JSON)
			.accept(MediaType.APPLICATION_JSON)
			.get(ClientResponse.class);

		//Pantalla y mensaje de retorno
		mav.setViewName("detailParkingPlace");
		if (response.getStatus() != 200) {
			ParkingPlace parkingPlace = response.getEntity(ParkingPlace.class);
			mav.addObject(parkingPlace);
		} else {
			mav.addObject(null);
		}
		
		return mav;
	}

	private double[] getLatLonAverage(List<ParkingPlace> listPPlaces) {
		double latTotal= 0;
		double lonTotal= 0;
		for (ParkingPlace parkingPlace : listPPlaces) {
			latTotal=latTotal + parkingPlace.getLatitud();
			lonTotal=lonTotal + parkingPlace.getLongitud();
		}
		
		double[] latlonAverage= {latTotal/listPPlaces.size(), lonTotal/listPPlaces.size()};
		
		return latlonAverage;
	}
}