/* Generates predictions using past data for journeys taking place at the specified times */
func predictJourneyTimesWithDetails(line, bound, fromStop, toStop string, times []time.Time, method performanceeval.Method,
	realTimeEstimatesCache map[string]map[string]map[time.Time]map[string]int64) (map[time.Time]time.Duration, map[time.Time]map[string]map[string]time.Duration, int) {
	intermediateStopsOrdered := selectdb.SelectIntermediateStops(line, bound, fromStop, toStop)
	intermediateStops := make(map[string]map[string]bool)
	for i := 0; i < len(intermediateStopsOrdered)-1; i++ {
		intermediateStops[intermediateStopsOrdered[i]] = map[string]bool{
			intermediateStopsOrdered[i+1]: true,
		}
	}

	predictions := make(map[time.Time]time.Duration)
	predictionsAdjacentStops := make(map[time.Time]map[string]map[string]time.Duration)

	for _, departureTime := range times {
		prediction, _, predictionAdjacentStops, _, _, _, err := performanceeval.PredictIndividualJourneyWithCache(line, bound, intermediateStops, intermediateStopsOrdered,
			departureTime, method, realTimeEstimatesCache)

		if err != nil {
			// If fail to generate prediction due to lack of historic data, skip
			continue
		}
		predictions[departureTime] = prediction
		predictionsAdjacentStops[departureTime] = predictionAdjacentStops
	}
	return predictions, predictionsAdjacentStops, len(intermediateStopsOrdered) - 1
}
/* Reconstruct for the predictions that were generated earlier*/
func lookupPredictionsUsed(line, bound string, intermediateStops map[string]map[string]bool, intermediateStopsOrdered []string,
	departureTime time.Time, method performanceeval.Method,
	realTimeEstimatesCache map[string]map[string]map[time.Time]map[string]int64,
	errorMessage *string) (time.Duration, time.Duration, map[string]map[string]time.Duration, map[string]map[string]time.Duration,
	map[string]map[string]time.Time, map[string]map[string]string) {

	prediction, stddev, predictionsAdjacentStops, stddevAdjacentStops, expectedDepartureTimesAtStops, mixedTypeAtStops, err := performanceeval.PredictIndividualJourneyWithCache(line, bound,
		intermediateStops, intermediateStopsOrdered, departureTime, method, realTimeEstimatesCache)

	if err != nil {
		logger.GetLogger().Error(err.Error())
		*errorMessage += fmt.Sprintf("Prediction '%v' does not account for certain stops due to lack of data\n",
			method.String())
	}
	return prediction, stddev, predictionsAdjacentStops, stddevAdjacentStops, expectedDepartureTimesAtStops, mixedTypeAtStops
}