class RateUpdaterService {

	@Transactional
	public void updateRates(List<Quote> quotes) {

		List<Quote> quotesList = new ArrayList<>(quotes);

		Collections.sort(quotesList, (o1, o2) -> o1.getTime().compareTo(o2.getTime()));

		List<LatestRate> existingLatestRates = latestRepo.findAll();

		List<LatestRate> newLatestRates = new ArrayList<>();
		List<Quote> newHistoricalRates = new ArrayList<>();

		List<SymbolEntity> symbols = symbolRepo.findAll();

		for (Quote quote : quotesList) {
			LatestRate existingLatestRate = getFromList(existingLatestRates, quote);

			if (existingLatestRate == null) {

				SymbolEntity fromcur = getFromList(symbols, quote.getCode());
				
				if(fromcur == null) {
					log.warn("Cannot find symbol '{}' in DB, skipping it.", quote.getCode());
					continue;
				}

				SymbolEntity tocur = getFromList(symbols, quote.getCurrency());

				if(tocur == null) {
					log.warn("Cannot find symbol '{}' in DB, skipping it.", quote.getCurrency());
					continue;
				}
				
				LatestRate newLatestRate = new LatestRate(fromcur, tocur, quote.getPrice(), quote.getTime());

				newLatestRates.add(newLatestRate);
				existingLatestRates.add(newLatestRate);

			} else if (quote.getTime().isAfter(existingLatestRate.getDate())) {
				existingLatestRate.setDate(quote.getTime());
				existingLatestRate.setValue(quote.getPrice());

				if (!newLatestRates.contains(existingLatestRate)) {
					newLatestRates.add(existingLatestRate);
				}
			}
			
			newHistoricalRates.add(quote);
		}

		latestRepo.saveAll(newLatestRates);

		rateService.addHistoricalRates(newHistoricalRates);

		if (!newLatestRates.isEmpty()) {
			bus.publishEvent(new RatesUpdatedEvent().setRates(rateMapper.mapToRates(newLatestRates)));
		}
	}

}