@POST
	@Path("/optimize")
	@Produces("application/json; charset=UTF-8")
	public BestPlanning processOptimize(String request) {
		try {
			List<Flight> flights = new ObjectMapper().readValue(request, new TypeReference<List<Flight>>(){});

			LOGGER.info("flightsCount: " + flights.size());
			if (flights.size() < 1000) {
				LOGGER.info("flights: " + request);
			}
			
			Comparator<Integer> reverseComparator = new Comparator<Integer>() {
				public int compare(Integer o1, Integer o2) {
					return o1.compareTo(o2) * (-1);
				}
			};
			
			// Construction de la map des vols par heure de départ
			NavigableMap<Integer, List<Flight>> flightsMap = new TreeMap<Integer, List<Flight>>(reverseComparator);
			for (Flight flight : flights) {
				List<Flight> mapValue = flightsMap.get(flight.getDepart());
				if (mapValue == null) {
					mapValue = new ArrayList<Flight>();
//					mapValue = new LinkedList<Flight>();
					flightsMap.put(flight.getDepart(), mapValue);
				}
				mapValue.add(flight);
			}
			
			// Stockage du meilleur planning par heure de départ
			Map<Integer, BestPlanning> bestPlanningMap = new HashMap<Integer, BestPlanning>(flightsMap.size());

			// Calcul du meilleur planning (en le calculant pour chaque heure de départ, de la dernière à la première)
			BestPlanning bestPlanning = new BestPlanning();
			int maxDepartureTime = flightsMap.firstKey();
			
			for (Map.Entry<Integer, List<Flight>> flightsEntry : flightsMap.entrySet()) {
				bestPlanning = computeBestPlanning(flightsEntry.getValue(), bestPlanning, bestPlanningMap, maxDepartureTime);
				bestPlanningMap.put(flightsEntry.getKey(), bestPlanning);
			}
			
			LOGGER.info("bestPlanningPathCount: " + bestPlanning.getPathSize());
			if (bestPlanning.getPathSize() < 1000) {
				LOGGER.info("bestPlanning: " + bestPlanning);
			}

			return bestPlanning;
		}
		catch (JsonProcessingException e) {
			throw new BadRequestException("Erreur lors du parsing JSON des vols en request", e);
		}
		catch (IOException e) {
			throw new BadRequestException("Erreur lors du parsing JSON des vols en request", e);
		}
		catch (StackOverflowError e) {
			throw new StackOverflowError("Erreur de récursion trop profonde, dûe à un très grand nombre de vols");
		}
	}